Проблема в том, что доступ к bool m_ThreadMayRun;
не синхронизирован, и в соответствии с правилами C ++ каждый поток может предполагать, что он не изменяется между потоками. Таким образом, вы получите расу (форма неопределенного поведения).
Чтобы прояснить намерение, сделайте его atomic
.
std::atomic<bool> m_ThreadMayRun;
С этим каждым грузом / хранилищем m_ThreadMayRun
становится ограничением памяти, которое не только синхронизирует свое собственное значение, но и делает другую работу , выполняемую потоком видимой, благодаря семантике получения / освобождения атома c загрузка / сохранение.
Хотя возможна небольшая гонка между m_ThreadMayRun = true
в потоке и настройкой m_ThreadMayRun = false
. Любой из них может быть выполнен первым, что иногда приводит к нежелательным результатам. Чтобы избежать этого, инициализируйте его как true
перед запуском потока.
std::atomic<bool> m_ThreadMayRun;
void main(){
m_ThreadMayRun = true;
thread mythread(&ThreadFunction);
//do stuff
m_ThreadMayRun = false;
mythread.join(); // this blocks endlessly even when I ask 'joinable' before
}
void ThreadFunction{
initdata();
while(m_ThreadMayRun){
//do stuff that can be / has to be done for ever
}
deinitdata();
}
Для получения дополнительной информации об ограждениях памяти и семантике получения / выпуска см. Следующие превосходные ресурсы: книга " C ++ параллелизм в действии " и atomic<>
оружия Херба Саттера разговора.