unique_ptr线程安全吗?以下代码是否无法两次打印相同的数字?
#include <memory>
#include <string>
#include <thread>
#include <cstdio>
using namespace std;
int main()
{
unique_ptr<int> work;
thread t1([&] {
while (true) {
const unique_ptr<int> localWork = move(work);
if (localWork)
printf("thread1: %d\n", *localWork);
this_thread::yield();
}
});
thread t2([&] {
while (true) {
const unique_ptr<int> localWork = move(work);
if (localWork)
printf("thread2: %d\n", *localWork);
this_thread::yield();
}
});
for (int i = 0; ; i++) {
work.reset(new int(i));
while (work)
this_thread::yield();
}
return 0;
}
答案 0 :(得分:34)
unique_ptr是线程安全的。你打破了不成文的规则:你永远不会通过引用传递线程之间的unique_ptr。
unique_ptr背后的理念是它始终拥有一个(唯一的)所有者。因此,您可以始终在线程之间安全地传递它而不进行同步 - 但您必须按值传递它,而不是通过引用传递它。为unique_ptr创建别名后,您将失去唯一性属性,并且所有赌注均已关闭。不幸的是,C ++不能保证唯一性,所以你要留下一个你必须遵循的惯例。不要为unique_ptr创建别名!
答案 1 :(得分:22)
不,它不是线程安全的。
两个线程都可能move
工作指针没有显式同步,因此两个线程都可以获得相同的值,或者两者都获得一些无效指针......它是未定义的行为。
如果你想做这样的正确的,你可能需要使用类似std::atomic_exchange
的东西,这样两个线程都可以用正确的语义读取/修改共享工作指针。
答案 2 :(得分:8)
根据Msdn:
以下线程安全规则适用于标准中的所有类 C ++库(除了shared_ptr和iostream类,如上所述 下文)。
单个对象是从多个线程读取的线程安全的。对于 例如,给定一个对象A,从线程1和A读取A是安全的 从线程2同时。
如果一个线程正在写入一个对象,那么所有读取 并且必须在相同或其他线程上写入该对象 保护。例如,给定对象A,如果线程1正在写入 A,然后必须阻止线程2读取或写入A。
即使是另一个实例,也可以安全地读取和写入一个类型的实例 线程正在读取或写入相同类型的不同实例。 例如,给定相同类型的对象A和B,如果是A则是安全的 在线程1中写入,在线程2中读取B.