Use “regular” variable to synchronize threads

2019-07-30 01:56发布

问题:

If I have only two threads, and I want one of them to wait for the other to reach a certain point, is it safe to do the following:

bool wait = true;

//Thread 1:
while(wait) ;
wait = true; //re-arm the signal

//Thread 2:
/* Preform here the code that needs to complete before Thread 1 continues */
wait = false;

Basically, if one thread only writes to it and the other only reads, can there be a problem? I assume a read or a write of a single bool is atomic, and even if not, I don't see how it can make a difference here.

回答1:

No, it can't work. If you use std::atomic<bool> instead it will work.

Atomics in C++ address three issues. First, the possibility that a thread switch will happen in the middle of storing or reading a value that requires more than one bus cycle; this is called "tearing". Second, the possibility that two threads will be running on two separate processors with two separate caches, and one thread won't see changes made by the other. This is called "cache coherency". Third, the possibility that the compiler will move code around because the order doesn't appear to matter.

Even though a bool value probably only requires one bus cycle to read or write, it doesn't address the other two issues.

There are no reliable shortcuts. Use proper synchronization.



回答2:

While you would get guarantees with an std::atomic<bool>, I think you could perhaps make it work with a simple volatile, because:

  • the compiler cannot reorder instructions on volatile values
  • one of the threads always write to the variable, so the instruction is effectively atomic
  • the other thread doesn't need to do the read and the write atomically

So there wouldn't be any form of tearing. However, the issue of cache coherency is still there, and that's hardware or OS dependent.