c – 在被另一个线程写入并在该线程加入之后从主线程访问变量是否安全?

前端之家收集整理的这篇文章主要介绍了c – 在被另一个线程写入并在该线程加入之后从主线程访问变量是否安全?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是线程安全的吗?
int x = 0;
std::thread([&]{ x = 1; }).join();
std::cout << x;

变量x可以从两个线程访问,而不使用原子或锁.但是,对join()的调用强制对x的访问是顺序的.@H_404_5@

这里需要内存屏障吗?@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@

原文链接:https://www.f2er.com/c/111468.html

猜你在找的C&C++相关文章