Если поток устанавливает флаг (или сигнализирует о событии) до своего выхода, это условие гонки. Поток еще не обязательно вернулся в ОС и все еще может выполняться.
Например, рассмотрим программу, которая загружает динамическую библиотеку (псевдокод):
lib = loadLibrary("someLibrary");
fun = getFunction("someFunction");
fun();
unloadLibrary(lib);
И давайте предположим, что эта библиотека использует ваш поток:
void someFunction() {
volatile bool finished_flag = false;
thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag);
while(!finished_flag) { // ignore the polling loop, it's besides the point
sleep();
}
delete thrd;
}
void myclass::mymethod() {
// do stuff
finished_flag = true;
}
Когда myclass::mymethod()
устанавливает finished_flag
в true
, myclass::mymethod()
еще не вернулся. По крайней мере, он все равно должен выполнить какую-то инструкцию «возврата» (если не намного больше: деструкторы, управление обработчиками исключений и т. Д.). Если поток, выполняющий myclass::mymethod()
, будет прерван до этой точки, someFunction()
вернется к вызывающей программе, и вызывающая программа выгрузит библиотеку. Когда поток, выполняющий myclass::mymethod()
, запланирован для повторного запуска, адрес, содержащий инструкцию return, больше не действителен, и программа вылетает.
Решением будет someFunction()
, чтобы позвонить thrd->join()
перед возвратом. Это гарантирует, что поток вернулся в ОС и больше не выполняется.