C++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 для потока, если вы хотите какой-то тип поведения тайм-аута в потоке?

3 ответов


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

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

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

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

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

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

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


std::thread::~thread()

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

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

это означает, что такая программа, как эта, не совсем хорошо сформирована или безопасна.

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

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


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

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

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