![](/img/trans.png)
[英]Shared lifecycle cross processes with boost::interprocess::shared_ptr
[英]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.