这个是否线程安全?
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()
的顺序会引入竞争条件。
x
变量,两个线程都会读取和/或写入它(第二个线程当然是通过引用来进行的)。变量x
实际上可能是在不同处理器上的两个副本,但处理器的工作是确保更改传播到所有副本(例如,参见MESI协议)。然而,这样的实现细节与语言无关。 - In silico