簡體   English   中英

多線程的shared_ptr破壞是否安全?

[英]Is shared_ptr destruction safe with multiple threads?

我有兩個類似的類:

class Foo {
 public:
  void bar() {
    std::lock_guard<std::mutex> lock(m_mutex);
    m_data.push_back('x');
  }
 private:
  std::string m_data;
  std::mutex m_mutex;
};

class Pool {
 public:
   static std::shared_ptr<Foo> Create(int index) {
     std::lock_guard<std::mutex> lock(m_mutex);
     if (m_pool.size() > 10) {
       m_pool.erase(m_pool.begin());
     }
     std::shared_ptr<Foo>& ptr = m_pool[index];
     if (!ptr) ptr.reset(new Foo);
     return ptr;
   }
 private:
   static std::mutex m_mutex;
   static std::map<int, std::shared_ptr<Foo>> m_pool;
};

以及運行此代碼的幾個線程:

void parallel_function(int index) {
  // several threads can get the same index
  std::shared_ptr<Foo> foo = Pool::Create(index);
  foo->bar();
}

Cppreference

所有成員函數(包括復制構造函數和復制賦值)都可以由shared_ptr的不同實例上的多個線程調用,而無需額外的同步,即使這些實例是副本並共享同一對象的所有權。 如果多個執行線程在沒有同步的情況下訪問相同的shared_ptr,並且這些訪問中的任何一個使用shared_ptr的非const成員函數,那么將發生數據爭用; 原子函數的shared_ptr重載可用於防止數據競爭。

兩個問題:

  1. 由於Pool::Create總是返回shared_ptr的副本,我假設每個shared_ptr的復制和銷毀都是線程安全的,如果它發生在m_pool.erase或者在parallel_function的末尾。 它是否正確?

  2. 我調用shared_ptr::operator-> ,這是一個const成員函數,函數Foo::bar是線程安全的。 這里有數據競爭嗎?

總結一下我的評論。

  1. 是的,這是線程安全的,因為您在不同的線程中操作shared_ptr的單獨副本。 這是少數幾個傳遞shared_ptr副本實際上是合理的情況之一。
  2. operator->是一個const成員 所以基本上你的代碼很好,只要Foo :: bar無競賽就是真的(現在很明顯)。

暫無
暫無

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

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