Is it safe to access a variable from the main stream after it has been recorded by another stream and after this stream has been attached?

Is it thread safe?

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

The variable x is accessed from two threads without using an atom or locks. However, a call to join() causes the calls to x to be sequential.

Is a memory barrier required here?

+6
source share
1 answer

Yes, this particular piece of code is thread safe; barriers or locks are not required.

This is the timeline of events regarding 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, there is no way to access x more than one thread. In fact, using join() effectively makes access to x available in sequential order, you guessed it. join() provides synchronization instead of the synchronization that you get from locks.

Basically, you have an example of how you can have multithreading with zero concurrency.

Of course, this is only true because of the call to join() , which occurs immediately after creating the stream in the provided code fragment. If you 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 

Reordering join() in this way will result in a race.

+11
source

Source: https://habr.com/ru/post/948871/


All Articles