Иногда я должен использовать std::thread
для ускорения моего приложения. Я также знаю, join()
ждет, пока поток не завершится. Это легко понять, но в чем разница между звонком detach()
и не звонком?
Я думал, что без detach()
, метод потока будет работать с использованием потока независимо.
Не отрываясь:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called without detach");
});
//some code here
}
Звонок с отрывом:
void Someclass::Somefunction() {
//...
std::thread t([ ] {
printf("thread called with detach");
});
t.detach();
//some code here
}
std
иboost
нити былиdetach
иjoin
моделируется близко после POSIX нитей.Ответы:
В деструкторе
std::thread
,std::terminate
называется, если:t.join()
)t.detach()
)Таким образом, вы должны всегда
join
илиdetach
поток, прежде чем потоки выполнения достигнут деструктора.Когда программа завершает работу (т.е.
main
возвращает), остальные ожидающие потоки, выполняющиеся в фоновом режиме, не ожидаются; вместо этого их выполнение приостанавливается и их локальные объекты потока разрушаются.Важно, что это означает, что стек этих потоков не разматывается, и поэтому некоторые деструкторы не выполняются. В зависимости от действий, которые должны были предпринять эти деструкторы, ситуация может быть такой же плохой, как если бы программа потерпела крах или была убита. Надеюсь, ОС снимет блокировки файлов и т. Д., Но вы могли повредить общую память, наполовину записанные файлы и т.п.
Итак, вы должны использовать
join
илиdetach
?join
detach
источник
Вы должны вызывать,
detach
если вы не собираетесь ждать завершения потока,join
но вместо этого поток просто продолжит работать до тех пор, пока он не будет завершен, а затем завершит работу, не ожидая, что основной поток ожидает его специально.detach
в основном высвободит ресурсы, необходимые для реализацииjoin
.Это фатальная ошибка , если объект потока не завершает свою жизнь и ни
join
ниdetach
был назван; в этом случаеterminate
вызывается.источник
Когда вы отсоединяете нить, это означает, что вы не должны делать
join()
это перед выходомmain()
.Библиотека потоков на самом деле будет ждать каждого такого потока ниже основной , но вы не должны заботиться об этом.
detach()
в основном полезно, когда у вас есть задача, которая должна быть выполнена в фоновом режиме, но вы не заботитесь о ее выполнении. Это обычно относится к некоторым библиотекам. Они могут молча создать фоновый рабочий поток и отключить его, чтобы вы даже не заметили этого.источник
Этот ответ направлен на ответ на вопрос в названии, а не на объяснение разницы между
join
иdetach
. Итак, когда следуетstd::thread::detach
использовать?В должным образом поддерживаемом коде C ++
std::thread::detach
не следует использовать вообще. Программист должен убедиться, что все созданные потоки корректно завершаются, высвобождая все полученные ресурсы и выполняя другие необходимые действия по очистке. Это подразумевает, что отказ от владения потоками путем вызоваdetach
не является вариантом и, следовательно,join
должен использоваться во всех сценариях.Однако некоторые приложения полагаются на старые и часто не очень хорошо разработанные и поддерживаемые API, которые могут содержать бесконечно блокирующие функции. Перемещение вызовов этих функций в отдельный поток, чтобы избежать блокировки других вещей, является обычной практикой. Невозможно изящно
join
завершить такой поток, поэтому его использование приведет лишь к блокировке основного потока. Это ситуация, когда использованиеdetach
было бы менее злой альтернативой, скажем, выделениюthread
объекта с динамической длительностью хранения, а затем преднамеренной утечке.источник
По данным cppreference.com :
Например:
Обратите внимание на локальную переменную:
my_thread
когда время жизниmy_thread
истекло,std::thread
будет вызываться деструктор иstd::terminate()
внутри деструктора.Но если вы используете
detach()
, вы не должны использоватьmy_thread
больше, даже если время жизниmy_thread
истекло, с новым потоком ничего не произойдет.источник
&
лямбда-захват, вы используете переменные окружения области видимости по ссылке - так что вам лучше быть уверенным, что время жизни любой ссылки, на которую вы ссылаетесь, больше, чем время жизни вашего потока.