will an atomic variable in if statement protect the if body?

Viewed 408

For example:

#include <atomic>

std::atomic_bool atomicBool(false);
int sharedVariable = 0;

void work() {
  if (atomicBool) {
    sharedVariable++; //will this line protected by atomic variable?
  }
}

will the statement sharedVariable++; protected to be thread safe by the atomicBool? If not (as a glimpse of the file I guess not), does that mean is this case I still need to use the mutex lock?

3 Answers

No.

Atomic variables are not mutexes.

They do not protect anything except reads and writes to themselves.

Even if they did, with this syntax, there is no way for the variable to "know" about the scope it's been named in.

It sounds like perhaps sharedVariable should be the atomic, though that is again not sufficient if you have more statements to protect as a block in your real code.

As the other answers have said, no, it is not protected in any meaningful way. What this answer adds is a concrete example.

I am assuming by "protect", you mean that you want to stop sharedVariable from being caught up in a race condition and undefined behaviour ensuing. For this to make sense, I am going to assume that you actually set atomicBool somewhere.

With that in mind, here's an example scenario of why your atomic is not sufficient:

  1. atomicBool is read by thread 1. It is true.
  2. atomicBool is read by thread 2. It is true.
  3. Both threads now attempt to change sharedVariable. This is a race condition!

Now suppose you set the atomic variable inside of the if statement like so:

if (atomicBool) {
    atomicBool = false;
    sharedVariable++;
}

This has a race condition of its own, here's an example of how it may occur:

  1. atomicBool is read by thread 1. It is true.
  2. atomicBool is read by thread 2. It is true.
  3. atomicBool is written by thread 1 to false.
  4. atomicBool is written by thread 2 to false.
  5. Both threads now attempt to change sharedVariable. This is a race condition!

There are "compare and change" / "test and set" checks you can use instead that do this atomically (i.e. the check and the write appear to happen at the same time for all observers).

Mutexes can help solve this problem, making the variable you want to change atomic can solve this problem, but it's hard to say which is more appropriate and whether or not you'll introduce more race conditions in the process without more context.

No, it will not protect the modification. Yes, you need to use mutex in such case, or make sharedVariable itself atomic.

Related