这是线程安全的吗?在主线程被另一个线程写入并且线程被加入后访问变量是否安全?
int x = 0;
std::thread([&]{ x = 1; }).join();
std::cout << x;
变量x是在不使用原子或锁的情况下从两个线程访问的。但是,拨打join()
强制对x的访问是连续的。
此处是否需要内存屏障?
这是线程安全的吗?在主线程被另一个线程写入并且线程被加入后访问变量是否安全?
int x = 0;
std::thread([&]{ x = 1; }).join();
std::cout << x;
变量x是在不使用原子或锁的情况下从两个线程访问的。但是,拨打join()
强制对x的访问是连续的。
此处是否需要内存屏障?
是的,那个特别的代码片段是线程安全的;不需要屏障或锁。
这是事件的时间表相对于你的代码:
thread 1
--------
|
int x = 0;
(write 0 to x)
|
std::thread thread 2
(start thread 2) --------> --------
| |
join(); x = 1;
(thread 1 suspended) (write 1 to x)
. |
. thread 2 returns
. |
(thread 1 resumes) <------- x
|
std::cout << x;
(read from x)
|
thread 1 returns
|
x
正如你所看到的,在任何一点x
由多于一个线程访问。实际上,正如你猜测的那样,使用join()
有效地使所有对x
的访问按顺序发生。 join()
提供了同步来代替从锁获得的同步。
基本上,你拥有的是一个如何使用零并发多线程的例子。
当然,这仅仅是因为调用join()
,这是在您提供的代码片段中创建线程后立即发生的。如果不是有这样的事情:
int x = 0;
std::thread t([&]{ x = 1; });
std::cout << x;
t.join(); // Move join() call here
的时间表,而不是看起来可能是这样:
thread 1
--------
|
int x = 0;
(write 0 to x)
|
std::thread thread 2
(start thread 2) --------> --------
| |
std::cout << x; x = 1;
(read from x) (write 1 to x) <-- PROBLEM!
| |
join(); |
(thread 1 suspended) |
. |
. thread 2 returns
. |
(thread 1 resumes) <------- x
|
thread 1 returns
|
x
改变的join()
这样的顺序将引入的比赛。
没有数据竞争=没有需要 – user2485710