簡體   English   中英

boost shared_ptr <XXX>線程安全嗎?

[英]Is boost shared_ptr <XXX> thread safe?

我有一個關於boost::shared_ptr<T>

有很多線程。

using namespace boost;

class CResource
{
  // xxxxxx
}

class CResourceBase
{
public:
   void SetResource(shared_ptr<CResource> res)
   {
     m_Res = res;
   }

   shared_ptr<CResource> GetResource()
   {
      return m_Res;
   }
private:
   shared_ptr<CResource> m_Res;
}

CResourceBase base;

//----------------------------------------------
// Thread_A:
    while (true)
    {
       //...
       shared_ptr<CResource> nowResource = base.GetResource();
       nowResource.doSomeThing();
       //...
    }

// Thread_B:
    shared_ptr<CResource> nowResource;
    base.SetResource(nowResource);
    //...

Q1

如果Thread_A不關心nowResource是最新的,那么這部分代碼會有問題嗎?

我的意思是當Thread_B完全沒有SetResource()Thread_A通過GetResource()得到一個錯誤的智能點?

Q2

線程安全是什么意思?

如果我不關心資源是否是最新的,那么當nowResource被釋放時, shared_ptr<CResource> nowResource會使程序崩潰,或者問題是否會破壞shared_ptr<CResource>

boost::shared_ptr<>提供一定程度的線程安全性。 引用計數以線程安全方式進行操作(除非您將boost配置為禁用線程支持)。

因此,您可以復制shared_ptr並正確維護ref_count。 你不能在多個線程中安全地做的是從多個線程修改實際的shared_ptr對象實例本身(例如從多個線程調用reset() )。 因此,您的使用不安全 - 您正在修改多個線程中的實際shared_ptr實例 - 您需要擁有自己的保護。

在我的代碼中, shared_ptr通常是按值傳遞的本地或參數,因此沒有問題。 從一個線程到另一個線程我通常使用線程安全隊列。

當然,這些都不能解決訪問shared_ptr指向的對象的線程安全問題 - 這也取決於您。

從boost 文檔

shared_ptr對象提供與內置類型相同的線程安全級別。 可以通過多個線程同時“讀取”(僅使用const操作訪問) shared_ptr實例。 可以通過多個線程同時“寫入”(使用諸如operator=或reset之類的可變操作來訪問) 不同的 shared_ptr實例(即使這些實例是副本,並在下面共享相同的引用計數。)

任何其他同時訪問都會導致未定義的行為。

因此,您的使用不安全,因為它使用m_res同時讀寫。 boost文檔中的示例3也說明了這一點。

您應該使用一個單獨的互斥鎖來保護對SetResource / GetResource m_res的訪問。

好吧,tr1 :: shared_ptr(基於boost)文檔講述了一個不同的故事,這意味着資源管理是線程安全的,而資源管理則不是。

” ...

線程安全

C ++ 0x-only功能包括:rvalue-ref / move支持,分配器支持,別名構造函數,make_shared和allocate_shared。 此外,采用auto_ptr參數的構造函數在C ++ 0x模式下已棄用。

Boost shared_ptr文檔的Thread Safety部分說“shared_ptr對象提供與內置類型相同的線程安全級別。” 實現必須確保對單獨的shared_ptr實例的並發更新是正確的,即使這些實例共享引用計數,例如

shared_ptr a(新A); shared_ptr b(a);

//線程1 //線程2

a.reset(); b.reset();

動態分配的對象必須由其中一個線程銷毀。 弱引用使事情變得更有趣。 用於實現shared_ptr的共享狀態必須對用戶透明,並且必須始終保留不變量。 共享狀態的關鍵部分是強弱參考計數。 對這些線程的更新需要是原子的並且對所有線程都是可見的,以確保正確清理托管資源(畢竟,這是shared_ptr的工作!)在多處理器系統上,可能需要內存同步,以便引用計數更新和銷毀托管資源是無競爭的。

......”

http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr

m_Res不是線程安全的,因為它同時讀/寫,你需要boost :: atomic_store / load函數來保護它。

//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write

添加,您的類具有循環引用條件; shared_ptr<CResource> m_Res不能是CResourceBase的成員。 您可以改用weak_ptr

暫無
暫無

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

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