c++ - Race Condition with std::atomic compare_exchange_strong - Stack Overflow

admin2025-04-16  3

I am getting into a race condition with 2 threads while using atomic CAS.

std::atomic<int> turn(0);
int free = 0;
void Work(int pid){
    while(true){
        if(turnpare_exchange_strong(free, pid)){
            std::cout << "Thread " << pid << " is running on core " << sched_getcpu() << std::endl;
            turn.store(free);
        }
    }
}
int main(){
    std::thread t1 = std::thread(Work, 1);
    std::thread t2 = std::thread(Work, 2);
    t1.join();
    t2.join();
}

Can someone please help me understand why the above code is not thread-safe?

I am getting into a race condition with 2 threads while using atomic CAS.

std::atomic<int> turn(0);
int free = 0;
void Work(int pid){
    while(true){
        if(turn.compare_exchange_strong(free, pid)){
            std::cout << "Thread " << pid << " is running on core " << sched_getcpu() << std::endl;
            turn.store(free);
        }
    }
}
int main(){
    std::thread t1 = std::thread(Work, 1);
    std::thread t2 = std::thread(Work, 2);
    t1.join();
    t2.join();
}

Can someone please help me understand why the above code is not thread-safe?

Share Improve this question asked Feb 3 at 14:27 ssinglassingla 391 silver badge5 bronze badges 6
  • 3 free should not be a global variable, but a local variable. – prapin Commented Feb 3 at 14:33
  • free is not getting modified. How does it matter? Sorry, can you please explain? – ssingla Commented Feb 3 at 14:36
  • 3 free is getting modified, read the docs – Ahmed AEK Commented Feb 3 at 14:39
  • 1 stackoverflow.com/questions/62863102/… – R.F. Commented Feb 3 at 14:40
  • Mutithreading is hard. Lock free programing is even harder. Based on mistake you've made, quality of question and code I would say you are trying level up your skills by multiple steps at once. – Marek R Commented Feb 3 at 15:17
 |  Show 1 more comment

1 Answer 1

Reset to default 4

In your code, you have:

std::atomic<int> turn(0);
int free = 0;

and then in Work():

if(turn.compare_exchange_strong(free, pid)) { … }

Both threads are using the same variable free as the expected value and, due to its modification by the compare_exchange_strong operation upon failure, the value of free may no longer be what you intended (which was 0).

Each thread should use its own local variable as the expected value.

void Work(int pid) {
    while(true) {
        int expected = 0;  // local copy of free
        if(turn.compare_exchange_strong(expected, pid)){
            std::cout << "Thread " << pid << " is running on core " << sched_getcpu() << std::endl;
            turn.store(0);
        }
    }
}
转载请注明原文地址:http://www.anycun.com/QandA/1744766638a87325.html