Подтвердить что ты не робот

С++ 11: Что произойдет, если вы не вызываете join() для std:: thread

Ниже приводится:

void test() 
{
  std::chrono::seconds dura( 20 );
  std::this_thread::sleep_for( dura );
}

int main()
{
  std::thread th1(test);
  std::chrono::seconds dura( 5 );
  std::this_thread::sleep_for( dura );
  return 0;
}

main выйдет через 5 секунд, что произойдет с th1, который все еще выполняется?

Продолжается ли выполнение до завершения, даже если объект потока th1, который вы определили в main, выходит из области действия и уничтожается?

Может ли th1 сидеть там после того, как он закончил выполнение или каким-то образом очистится, когда программа завершится?

Что делать, если поток был создан в функции, а не main - работает ли поток до тех пор, пока программа не завершится или когда функция выходит из области видимости?

Можно ли просто не называть join для потока, если вы хотите, чтобы какой-то тип тайм-аута в потоке?

4b9b3361

Ответ 1

Если вы не отсоединили или не присоединились к нити при вызове деструктора, он вызовет std::terminate, мы увидим это, перейдя в черновик C + +11 стандарт, мы видим, что раздел 30.3.1.3 thread destructor говорит:

Если joinable(), вызывает std:: terminate(). В противном случае эффект не имеет. [ Примечание. Либо неявное разделение или объединение потока joinable() в его деструктор может привести к затруднению отладки правильности (для detach) или производительности (для объединения), возникающие только тогда, когда исключение. Таким образом, программист должен обеспечить, чтобы destructor никогда не выполняется, пока поток все еще соединяется. -конец примечание]

так как для обоснования этого поведения мы можем найти хорошее резюме в (Not), используя std:: thread

Почему деструктор соединяемого потока должен вызывать станд:: прекратить? В конце концов, деструктор может присоединиться к ребенку поток, или он может отсоединиться от дочернего потока, или он может отменить нить. Короче говоря, вы не можете присоединиться к деструктору, поскольку это приводят к неожиданному (не указанному явно в коде) программе замерзнуть в случае f2 бросков.

и пример следует, а также говорит:

Вы не можете отсоединиться, так как это будет рисковать ситуацией, когда основная нить оставляет область, в которую был запущен дочерний поток, и ребенок поток продолжает работать и сохраняет ссылки на область, которая уже ушел.

В статье упоминается N2802: просьба пересмотреть отрыв на уничтожение для объектов потока, что является аргументом против предыдущего предложения, которое было отсоединено от разрушение, если оно соединяется, и отмечает, что одна из двух альтернатив будет заключаться в том, чтобы присоединиться к ней, что может привести к взаимоблокировкам, другая альтернатива - это то, что мы имеем сегодня, которое является std::terminate при уничтожении, если оно возможно.

Ответ 2

std::thread::~thread()

Если * имеет связанный поток (joinable() == true), std::terminate() называется

Источник: http://en.cppreference.com/w/cpp/thread/thread/~thread

Это означает, что программа, подобная этой, совсем не корректна или безопасна.

Обратите внимание, однако, что boost::thread::~thread() вызывает detach() вместо этого в этом случае. (как пользователь dyp, указанный в комментариях, это поведение устарело в более поздних версиях)

Вы всегда можете обойти это с помощью RAII. Просто оберните свою нить внутри другого класса, которая будет иметь желаемое поведение при уничтожении.

Ответ 3

В С++ 11 вы должны явно указать "что происходит", когда вновь созданный поток выходит за пределы области (наш вызов dtor вызывается). Иногда, когда мы уверены, что основной поток продолжается, и наши потоки действуют как "конвейер", безопасно "отделять" их; и иногда, когда мы ждем, когда наши потоки WORKER завершат свои операции, мы присоединяем их к ним.

Как это, программист должен убедиться, что деструктор никогда не выполняется, пока поток все еще совместим.

Укажите многопоточную стратегию. В этом примере вызывается std::terminate().