这是线程安全的吗?
int x = 0; std::thread([&]{ x = 1; }).join(); std::cout << x;
变量x可以从两个线程访问,而不使用原子或锁.但是,对join()的调用强制对x的访问是顺序的.@H_404_5@
这里需要内存屏障吗?@H_404_5@
解决方法
是的,该特定代码段是线程安全的;不需要障碍物或锁.
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()提供同步来代替从锁获得的同步.@H_404_5@
基本上,您所拥有的是一个如何使用零并发进行多线程处理的示例.@H_404_5@
当然,这只是因为调用join(),这是在您提供的代码片段中创建线程后立即发生的.如果你有这样的事情:@H_404_5@
int x = 0; std::thread t([&]{ x = 1; }); std::cout << x; t.join(); // Move join() call here
时间轴可能如下所示:@H_404_5@
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()的顺序将引入一场比赛.@H_404_5@