0

I am looking for some clarity on the necessity to lock a variable if std::atomic<> is used on it. Please consider the following code:

std::atomic<int> my_integer;

void Thread1()
{
    if (condition1)
    {
       my_integer = 5;
    }
   
    if (my_integer == 7)
    {
        doSomething();
    }
}

void Thread2()
{
    if (condition2)
    {
        my_integer = 7;
    }
}

Is there any reason to use a mutex around the writes and reads to my_integer? Or would the atomic variable provide adequate thread safe protection? Is there a possibility of any race condition occurring here? If so, what would that race condition be? Thanks in advance for any insight!

I was thinking that std::atomic should protect the assignment to my_integer, so that whenever it is read, it is always the most up-to-date version of the variable.

15
  • 3
    @Yksisarvinen: That's not correct, there is no UB here. Access to non-atomic shared data must be synchronized. But it is perfectly fine to not be able to predict the value of an atomic object. The code here has defined behavior - it will either call doSomething() or not call it, and it is unspecified which will be the case, but it will not behave unpredictably otherwise. If it were truly UB, it could also legally print out insulting messages about your mother - but the code here must not do any such thing. Commented Dec 15, 2023 at 17:26
  • 3
    @Yksisarvinen: The code is very likely not useful, and may be buggy in that it may not be doing what the author wants, but its behavior in terms of the C++ standard is well defined. Commented Dec 15, 2023 at 17:27
  • 3
    @Yksisarvinen: They do have a total order. On any given run of the program, either the store of 5 precedes the store of 7, or vice versa. But it could be different from one run to the next, and we are not directly informed as to which one it is. Commented Dec 15, 2023 at 18:19
  • 4
    @Yksisarvinen: Being able to make unsequenced reads and writes is the entire point of an atomic object. The memory ordering rules don't necessarily let you deduce with certainty the value that any given atomic load will return, but they do let you deduce the set of possible values, and if your program logic can deal with all of them, you are fine. Commented Dec 15, 2023 at 18:24
  • 4
    @Yksisarvinen: As a very basic example, think of an atomic object used to implement a spinlock mutex: when you go to lock it, you don't know in advance whether you will get the value 0 (the lock is available) or 1 (it is taken). But you handle both alternatives: if 1, you spin and retry; if 0, you take the lock and proceed into the critical section. Commented Dec 15, 2023 at 18:25

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.