这是线程安全的吗?
int x = 0;
std::thread([&]{ x = 1; }).join();
std::cout << x;
变量 x 从两个线程访问,而不使用原子或锁。但是,对 x 的调用 join()
强制对 x 的访问是顺序的。
这里需要内存屏障吗?
这是线程安全的吗?
int x = 0;
std::thread([&]{ x = 1; }).join();
std::cout << x;
变量 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()
将引入比赛。