Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will a calling thread see modifications to local variables after thread.join()?

In the simplest possible example, let's say I have a function that starts a thread, which in turn sets the value of a local variable to true. We join the thread, then leave the function.

bool func() {
    bool b = false;
    std::thread t([&]() { b = true; }); 
    t.join();
    return b;
}

Will this function return true, or is the behavior undefined?

like image 691
Alecto Irene Perez Avatar asked Mar 04 '23 01:03

Alecto Irene Perez


1 Answers

Yes, it must return true.

[thread.thread.member]

void join();

4 Effects: Blocks until the thread represented by *this has completed.

5 Synchronization: The completion of the thread represented by *this synchronizes with ([intro.multithread]) the corresponding successful join() return.

So the execution of the thread represented by the handle, and associated side effects are done before join returns to the calling context.

Example

Let's look at two functions, which differ only in when they join a thread:

int count_A() {
    int counter = 0;
    bool flag(true);
    auto t = std::thread([&]{flag = false;});

    while(flag) {    // infinite loop - flag never synchronized
        ++counter;
    }
    t.join();        // joins thread after loop exits
    return counter;
}
int count_B() {
    int counter = 0;
    bool flag(true);
    auto t = std::thread([&]{flag = false;});

    t.join();       // joins thread before loop, forcing synchronization
    while(flag) {
        ++counter;
    }
    return counter;
}

When compiled with g++ version 8.2 at -O3 optimization, invoking count_A results in an infinite loop because the compiler assumes flag is always true.

On the other hand, invoking count_B will just return a value of 0. Because the value of flag is checked after thread.join(), it's value is re-loaded, and flag is false so the while loop doesn't execute.

Note that if flag is changed to an atomic_bool, then count_A has the intended behavior of incrementing the counter until the flag is set to false, and the function does not enter an infinite loop (instead returning once flag is set to false by the child thread).

like image 174
4 revs, 2 users 53% Avatar answered Apr 07 '23 03:04

4 revs, 2 users 53%