簡體   English   中英

boost :: interprocess :: shared_ptr threadsafe(和進程間安全)?

[英]Is boost::interprocess::shared_ptr threadsafe (and interprocess-safe)?

我想在線程之間共享數據,並在最后一個用戶完成后自動刪除它。 大多數情況下,這似乎在boost::fixed_managed_shared_memory段中使用boost::interprocess::shared_ptr :但並非總是如此。

那么,是boost::interprocess::shared_ptr線程(和進程間)-safe?

如果我在固定地址使用我的共享內存(我很確定這在我的64位(井,48位)地址空間中可以正常),是否可以使用普通的boost::shared_ptr而不是boost::shared_ptr (線程安全)?

一些澄清:

我使用的指針類型是plain void* ,(我的共享內存映射到固定地址)。

線程安全的問題是關於引用計數 - 即,是否允許同時復制/銷毀在不同進程中同一事物的共享指針。 不能訪問不同線程中的相同共享指針,也不能訪問指針。

boost::interprocess:shared_ptr中使用的引用計數是使用boost/interprocess/detail/atomic.hpp定義的原子計數器實現的, boost/interprocess/detail/atomic.hpp邏輯主要由boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp 目的是以線程(和進程間)安全的方式處理引用計數。

原子操作實現因具體目標平台而異(Windows使用Win32 Interlocked API,某些平台使用各種內聯匯編等)。 了解您要定位的平台可能會有所幫助。 我想你可能會遇到refcount處理中的錯誤,盡管我不會指望它。

我已經將上述答案限制在你想要專門解決的領域:

線程安全的問題是關於引用計數 - 即,是否允許同時復制/銷毀在不同進程中同一事物的共享指針。 不能訪問不同線程中的相同共享指針,也不能訪問指針。

也就是說,我會查看可能由您在上面提到的項目引入的錯誤,或者通過某種方式創建“獨立” boost::interprocess:shared_ptr對象(其中不同的shared_ptr使用不同的refcounts引用相同的對象)。 如果你有一些代碼繼續使用和/或傳遞原始對象指針,這種情況很容易發生。

boost::shared_ptr<T>不是進程間安全的,所以在這種情況下它是否是多線程安全的是沒有實際意義的。 (該陳述假定BOOST_SP_DISABLE_THREADS未被#defined用於程序的操作。)

boost::interprocess::shared_ptr<T>就其本質而言,設計為跨進程安全,以及其本質上的多線程安全。 當最后一個引用超出范圍時,可以清除指向的對象。 顯然,這種清理發生在用於對象的共享內存段的范圍內。

由於boost::shared_ptr<T>在許多平台上使用1.33.0版本的無鎖計數機制 ,因此除了最有可能在shared_memory段中跨對象刪除對象成功的可能性之外,它是不可能的。似乎Boost維護者不支持這些功能。

呃。 boost::shared_ptr絕對不是線程安全的。 至少不比例如std::vector更安全。 您可以從多個線程讀取boost::shared_ptr ,但只要任何線程正在編寫boost::shared_ptr它就必須與其他編寫器讀取器同步。

不,你不能在共享內存中使用它,它從來沒有設計過。 例如,它使用一個所謂的“共享計數”對象來存儲引用計數和刪除器,並且該共享計數對象由shared_ptr代碼分配,因此它不會駐留在共享內存中。 此外, shared_ptr代碼(以及類似vtable的元數據)可能在不同進程中處於完全不同的地址,因此任何虛函數調用也都是一個問題(IIRC shared_ptr在內部使用虛函數 - 或者至少是函數指針,這導致同樣的問題)。


我不知道 boost::interprocess::shared_ptr是否是進程間安全的,但我很確定它不是。 進程間同步非常昂貴。 擁有boost::interprocess::shared_ptr 這樣做能夠為用戶阻止訪問共享數據。 這樣,對於連續多次訪問,只需支付一次高同步成本。

編輯:我希望 Eamon Nerbonne在他的評論中提到的使用模式(使用boost::shared_ptr是線程安全的),對於boost::interprocess::shared_ptr也是可以的。 雖然不能肯定地說。

“大多數情況下,這似乎在boost :: fixed_managed_shared_memory段中使用boost :: interprocess :: shared_ptr:但並非總是如此。” 如果並不總是意味着刪除總是不起作用:只需使用一個信號量與您的線程安全容器。 此信號量不會提高線程安全性,但您可以驗證甚至限制用戶使用數據的數量。 如果信號量為0,則不再有用戶,安全刪除共享數據。 如果那里只有一個用戶,則為1,因此請復制出用戶請求的數據,刪除共享容器,然后返回副本。

通過查看shared_ptr.hpp中的代碼以及boost網站上的文檔,似乎解除引用單個實例可能是也可能不是線程安全,具體取決於第二個模板參數,該參數決定了要使用的內部指針類型。 具體來說,“內部指針與typename VoidAllocator :: pointer類型具有相同的指針類型(即,如果typename VoidAllocator :: pointer為offset_ptr,則內部指針將為offset_ptr)。” 由於dereferences只返回此類的get()/ get_pointer()方法的結果,它應該完全取決於它。 如果您想要同時進行只讀訪問,Boost :: shared_ptr將起作用。 對於來自多個線程的寫訪問,您可能必須在offset_ptr之后編寫自己的包裝器。

正如pgroke暗示(不確定為什么是downvotes)核心問題是你是否從不同的線程或進程訪問同一個 shared_ptr實例。

shared_ptr(進程間或非進程)不支持此方案,這不安全。

另一方面,shared_ptr被設計為具有多個(線程私有,或通過某些其他機制來防止並發修改)共享指針實例指向同一對象,並且同時修改這些指向同一對象的不同實例問題。

:: interprocess ::這里主要是一個red-herring - 它不會改變指針的線程安全性,只是確保沒有內部指針引用進程私有內存等。

那兩個案例中的哪一個呢?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM