c++multithreadingsynchronizationatomictest-and-set

Mixing lock-less and lock-full thread synchronization with atomic TestAndSet in C++


I have a consumer thread that must read from a buffer without locking. It is fine if the operation must be skipped because a producer thread is writing to the buffer. So, the most appropriate choice seems to me to be an atomic TestAndSet on some flag.

Now, those aforementioned producer threads must respect this flag as well, because they can't start writing to the buffer while the consumer is reading from it. I could solve this using atomic_flag::test_and_set like the following code:

while (flag.test_and_set()) 
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

...but writing my own spin lock seems less than ideal. I would rather have my thread sleep until it is woken as a result of the flag being cleared. Something like:

flag.enter();

TLDR: How best to synchronize two threads where one can lock and the other can't?


Solution

  • Use a std::mutex.

    The readers can use try_lock to avoid blocking.

    The writers (producers) can use the blocking lock function as usual.

    Of course, to avoid leaking a lock, use std::unique_lock. Readers should pass std::try_to_lock as the second argument. You should then check owns_lock() to see whether the data can be safely read or a write was in progress.