简体   繁体   English

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

[英]Is it safe to access a variable from the main thread after it was written to by another thread and after that thread was joined?

Is this thread-safe? 这是线程安全的吗?

int x = 0;
std::thread([&]{ x = 1; }).join();
std::cout << x;

Variable x is accessed from two threads without using atomics or locks. 变量x可以从两个线程访问,而不使用原子或锁。 However, the call to join() forces the accesses to x to be sequential. 但是,对join()的调用强制对x的访问是顺序的。

Is a memory barrier required here? 这里需要内存屏障吗?

Yes, that particular code snippet is thread safe; 是的, 该特定代码段是线程安全的; barriers or locks are not required. 不需要障碍物或锁。

This is the timeline of events with respect to your code: 这是与您的代码相关的事件的时间表:

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

As you can see, at no point is x being accessed by more than one thread. 正如您所看到的, x不会被多个线程访问。 In fact, the use of join() effectively makes all accesses to x happen in sequential order , as you've surmised. 实际上, join()的使用有效地使得对 x 所有访问 按顺序发生 ,正如您所推测的那样。 The join() provides the synchronization in lieu of the synchronization you get from locks. join()提供同步来代替从锁获得的同步。

Basically, what you have is an example of how you can have multithreading with zero concurrency. 基本上,您所拥有的是一个如何使用零并发进行多线程处理的示例。

Of course, this is true only because of the call to join() , which happens immediately after you create the thread in the code snippet you provide. 当然,这只是因为调用join() ,这是在您提供的代码片段中创建线程后立即发生的。 If you instead had something like this: 如果你有这样的事情:

int x = 0;
std::thread t([&]{ x = 1; });
std::cout << x;
t.join(); // Move join() call here

The timeline instead may look like this: 时间轴可能如下所示:

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

Changing the order of join() in this manner will introduce a race. 以这种方式改变join()的顺序将引入一场比赛。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM