if executes when bool variable is false, in multithread senario

82 views Asked by At

I'm working on a project, and encountered this weired problem. A detached threaded is used, and the stop flag is a boolen variable inside a structure which is passed by pointer of pointer(due to project needed). a simplified code that can produce the problem is attached here.

#include <iostream>
#include <thread>
#include <chrono>
struct weired
{
    bool flag;
};

void hello_thread(void** stop)
{
    weired* c = (weired*)*stop;

    while (!(c->flag)) {

        if (c->flag)
        {
            std::cout << "weired happened!,  c->flag value is " << c->flag << std::endl;
            break;
        }
    }
    std::cout << "thread released" << std::endl;


}

int open(void** handle)
{
    *handle = new weired;
    weired* a = (weired*)*handle;
    a->flag = false;
    std::thread t(hello_thread, handle);
    t.detach();
    return 0;
}

int  close(void** handle)
{
    weired* a = (weired*)*handle;
    a->flag = true;
    delete a;
    return 0;
}

int main()
{
    int n;
    void* handle;
    n = open(&handle);

    std::cin >> n;

    n = close(&handle);


    return 0;
}

The cin in main funciton is for waiting purpose, and when the problem happened I don't input anything, so main fucntion just stuck at cin, just before calling close() function, so the "a->flag = true;" is not executed. Considering that "std::thread t" is created after "a->flag = false;" in open() function, so when the subthread starts to run, all flag should evaluate as false, right?

The problem i encoutered is that, the subthread can enter while loop, seemed that c->flag was false, but it could aslo enter if statement and the loop was breaked, then thread quited since loop was done, so c->flag seemed to be true? but when printed its value inside if statement, the printed value was 0, still seemed that c->flag is false. then why if statement executed? weired behavior

the project is on Visual Studio Community 2019, version 16.11.29 , target is release Win32. when in debug mode, this problem doesn't happen.

i also tried the same code on linux with g++ 11.4.0. when with -O2, subthread quit at startup, seems c->flag evaluates to true. but with -O1, subthread doesn't quit. linux g++ behavior

so the compiler optimization causes this problem? Can compiler optimizes the thread creating executed before "a->flag = false; " ? but why if statement behaves so weired?

I tried replace bool with atomic<bool> type, and in this simplified code it worked, but in the real project it didn't.

Sorry for my poor English.

1

There are 1 answers

1
why stuff works On

Having std::atomic is not always the solution for all data race problems.

What I see in your code is there are lot of read/write concurrent operations on the bool variable where the state can change any time.

What you need is some kind of locking mechanism, guard the flow until you read/write is done.