Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

thread::join() blocks when it shouldn't

To understand how to use atomics in C++11, I tried to following code snippet:

#include <iostream>
#include <thread>
#include <atomic>

using namespace std;

struct solution {
    atomic<bool> alive_;
    thread thread_;

    solution() : thread_([this] {
        alive_ = true;
        while (alive_);
    }) { }
    ~solution() {
        alive_ = false;
        thread_.join();
    }
};

int main() {
    constexpr int N = 1; // or 2
    for (int i = 0; i < N; ++i) {
        solution s;
    }
    cout << "done" << endl;
}

If N equals 1, the output is done. However, if I set it to 2, the main thread blocks at thread::join(). Why do you think we don't see done when N > 1?

Note: If I use the following constructor:

    solution() : alive_(true), thread_([this] {
        while (alive_);
    }) { }

it prints done for any value of N.

like image 271
Benji Mizrahi Avatar asked Dec 08 '22 04:12

Benji Mizrahi


1 Answers

If you don't initialise alive_ and only set it once the thread starts, the following interleaving of execution is possible:

MAIN: s::solution()
MAIN: s.thread_(/*your args*/)
MAIN: schedule(s.thread_) to run
thread: waiting to start
MAIN: s::~solution()
MAIN: s.alive_ = false
thread: alive_ = true
MAIN: s.thread_.join()
thread: while(alive_) {}
like image 64
Angew is no longer proud of SO Avatar answered Jan 14 '23 13:01

Angew is no longer proud of SO