Leo*_*all 15 c++ multithreading weak-ptr c++11
std::shared_ptr<int> g_s = std::make_shared<int>(1);
void f1()
{
std::shared_ptr<int>l_s1 = g_s; // read g_s
}
void f2()
{
std::shared_ptr<int> l_s2 = std::make_shared<int>(3);
std::thread th(f1);
th.detach();
g_s = l_s2; // write g_s
}
Run Code Online (Sandbox Code Playgroud)
关于上面的代码,我知道不同的线程读取和写入相同的shared_ptr导致竞争条件.但是怎么样weak_ptr?下面的代码中是否有竞争条件?(我的平台是Microsoft VS2013.)
std::weak_ptr<int> g_w;
void f3()
{
std::shared_ptr<int>l_s3 = g_w.lock(); //2. here will read g_w
if (l_s3)
{
;/.....
}
}
void f4()
{
std::shared_ptr<int> p_s = std::make_shared<int>(1);
g_w = p_s;
std::thread th(f3);
th.detach();
// 1. p_s destory will motify g_w (write g_w)
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*ger 32
我知道我迟到了,但是在搜索"weak_ptr线程"时会出现这种情况,而Casey的回答并不是全部真相.二者shared_ptr并weak_ptr可以从线程使用而无需进一步的同步.
因为shared_ptr,有很多文档(例如在cppreference.com或stackoverflow上).您可以安全地shared_ptr从不同的线程访问该对象.你无法从两个线程敲击相同的指针.换一种说法:
// Using p and p_copy from two threads is fine.
// Using p from two threads or p and p_ref from two threads is illegal.
std::shared_ptr<A> p = std::make_shared<A>();
std::shared_ptr<A> &p_ref = p;
std::shared_ptr<A> p_copy = p;
Run Code Online (Sandbox Code Playgroud)
要在代码中解决该问题,请将g_s参数(按值)传递给*f1().
对于弱指针,安全保证隐藏在weak_ptr :: lock的文档中:
有效地返回
expired() ? shared_ptr<T>() : shared_ptr<T>(*this),以原子方式执行.
您可以使用从其他线程weak_ptr::lock()获取a shared_ptr而无需进一步同步.这也证实了这里的升压和这个苏答案克里斯小丑,年轻.
同样,你必须确保不修改相同weak_ptr,而从另一个访问它从一个线程,所以传球g_w到f3()由价值为好.
shared_ptr并且weak_ptr属于与所有其他标准库类型相同的全面线程安全要求:如果成员函数是非修改性的 ( const),则对成员函数的同时调用必须是线程安全的(详见 C++11 §17.6.5.9 数据竞争避免 [res. data.races])。赋值运算符显然不是 const。
为了在下面的讨论中简洁起见,不同的weak_ptrs 和shared_ptrs 都从相同的原始生成shared_ptr或unique_ptr将被称为“实例”。在此分析中不需要考虑不共享同一对象的weak_ptrs 和shared_ptrs。评估线程安全的一般规则是:
const在同一实例上同时调用成员函数是线程安全的。所有观察者函数都是const.下表显示了两个线程同时在同一实例上运行时的线程安全性。
+---------------+----------+-------------------------+------------------------+
| operation | type | other thread modifying | other thread observing |
+---------------+----------+-------------------------+------------------------+
| (constructor) | | not applicable | not applicable |
| (destructor) | | unsafe | unsafe |
| operator= | modifier | unsafe | unsafe |
| reset | modifier | unsafe | unsafe |
| swap | modifier | unsafe | unsafe |
| use_count | observer | unsafe | safe |
| expired | observer | unsafe | safe |
| lock | observer | unsafe | safe |
| owner_before | observer | unsafe | safe |
+---------------+----------+-------------------------+------------------------+
Run Code Online (Sandbox Code Playgroud)
所述的std cppreference讨论::原子(标准::的weak_ptr)是最明显的上同时访问不同实例的安全性:
注意 std::weak_ptr 和 std::shared_ptr 使用的控制块是线程安全的:不同的非原子 std::weak_ptr 对象可以使用可变操作(例如 operator= 或 reset)同时被多个线程访问,甚至当这些实例是副本或以其他方式在内部共享相同的控制块时。
C++20 引入了std::atomic弱指针的特殊化,它通过适当的同步提供对同一实例的线程安全修改。请注意,对于构造函数,从另一个实例初始化不是原子的。例如,atomic<weak_ptr<T>> myptr(anotherWeakPtr);不是原子操作。