unique_ptr线程安全吗?

时间:2012-07-14 09:28:13

标签: c++ multithreading c++11 thread-safety unique-ptr

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;
}

3 个答案:

答案 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.