1

Suppose I have 2 threads : std::thread thd1; std::thread thd2; Thread thd1 periodically sets some global variable calling the folowing setFlag function :

static std::int32_t g_flag;
static std::mutex io_mutex;

void setFlag( std::int32_t flag )
{
   //std::lock_guard<std::mutex> lk(io_mutex);
   g_flag = flag;
}

And thread thd2 periodically reads this flag

std::int32_t getFlag()
{
   //std::lock_guard<std::mutex> lk(io_mutex);
   return g_flag;
}

The question is - should I use mutex in this case? Is it safe to access variable in read-write manner from several threads without having mutex?

Dmitry
  • 1,472
  • 15
  • 25

1 Answers1

5

Accessing a memory location for a write in one thread and either a read or write in another thread without synchronization and at least one of them non-atomically, is known as a data race and causes undefined behavior in C++.

In your code the write access to g_flag of thread 1 is not synchronized with the read access of thread 2 to the same variable.

Therefore your program has undefined behavior (as none of the accesses are atomic).

One possible solution for this is to use a mutex as you are demonstrating correctly in the commented code, which will synchronize the read and write access, such that one happens-before the other, although the order in which these happen-before is still indeterminate.

Another possibility is to declare g_flag as an atomic:

std::atomic<std::int32_t> g_flag{};

As mentioned above, atomic accesses (which std::atomic provides) are specifically exempt from causing data races and undefined behavior when accessed potentially in parallel for write and read.

An atomic will (in general) not make the other thread wait as a mutex/lock does. This does however also make it trickier to use correctly if you are accessing other shared memory as well.

Instead there are further options for std::atomic to specify whether and how other memory accesses around the atomic access will be ordered, i.e. whether and to what degree it will also cause synchronization between the threads.

Without further details I cannot determine what the appropriate tool is in your case.

walnut
  • 20,566
  • 4
  • 18
  • 54