Да, он должен вернуть true.
[thread.thread.member]
void join();
4 Эффекты : блокируется до тех пор, пока поток, представленный *this
, не завершится.
5 Синхронизация : завершение потока, представленного *this
, синхронизируется с ([intro.multithread]) соответствующим успешным возвратом join()
.
Таким образом, выполнение потока, представленного дескриптором, и связанные с ним побочные эффекты выполняются до того, как join
вернется в контекст вызова.
Пример
Давайте посмотрим на две функции, которые отличаются только тем, когда они присоединяются к потоку:
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;
}
При компиляции с g++ версии 8.2 с оптимизацией -O3
вызов count_A
приводит к бесконечному циклу, поскольку компилятор предполагает, что flag
всегда истинно.
С другой стороны, вызов count_B
просто вернет значение 0
. Поскольку значение flag
проверяется после thread.join()
, оно загружается повторно, а флаг равен false
, поэтому цикл while не выполняется.
Обратите внимание, что если flag
изменить на atomic_bool
, то count_A
будет увеличивать счетчик до тех пор, пока флаг не будет установлен в false, а функция не войдет в бесконечный цикл (вместо того, чтобы вернуться после того, как flag
будет устанавливается в false дочерним потоком).
person
Community
schedule
01.05.2019