I recently asked "Thrown object cannot be caught in a multi-threaded solution" and got the correct answer which works perfectly. However, I am still confused why there can be a race condition when only one thread does the write operation. Let me paste the original problematic code:
#include <iostream>
#include <thread>
using namespace std;
struct solution_using_thread {
solution_using_thread()
: alive_(true), thread_() {
thread_ = thread([this]() {
while(alive_);
});
}
~solution_using_thread() {
alive_ = false;
thread_.join();
}
private:
bool alive_;
thread thread_;
};
int main() {
cout << 0 << endl;
try {
solution_using_thread solution;
throw 1;
} catch (int i ) {
cout << i << endl;
}
cout << 2 << endl;
}
Sometimes the output is only
0
According to the linked question, if I instead use member atomic<bool> alive_, the output becomes as expected
0
1
2
Now, I am trying to reason why member bool alive_ causes Undefined Behavior.
Case 1 (Happy ending):
- Variable
solutionis initialized:solution_using_thread's default constructor setsalive_totruein the main thread.- The thread starts and the value of
alive_happens to betruein the second thread. So thread execution is stuck in thewhileloop. - Before constructor returns, the second thread has already been started.
- We
throw 1.- The destructor of
solutionis called. The value ofalive_istruein the main thread. thread.join()blocks until the value ofalive_is synchronized with the second thread.- After some finite amount of delay
alive_is synchronized, the while loop terminates, the second thread finishes, thethread_.join()returns and stack unwinding is happily completed.
- The destructor of
- The output is
0 1 2
Case 2 (Not desired, but at least not 'Undefined Behavior'):
- Variable
solutionis initialized:solution_using_thread's default constructor setsalive_totruein the main thread.- The thread starts and the value of
alive_happens to befalsein the second thread. So thread execution ends immediately. - Before constructor returns, the second thread have already been started.
- We
throw 1thread.join()returns immediately because the thread has already finished.
- The output is
0 1 2
Obviously there is at least one more case in which it prints only 0. Can you describe that case?
Aucun commentaire:
Enregistrer un commentaire