Когда следует использовать std::thread:: detach?
иногда я должен использовать 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
}
4 ответов
в деструкторе std::thread
, std::terminate
вызывается, если:
- нить не была соединена (с
t.join()
) - и тоже не отделился (с
t.detach()
)
таким образом, вы всегда должны быть либо join
или detach
поток до того, как потоки выполнения достигнут деструктора.
когда программа завершает работу (т. е. main
returns) остальные отсоединенные потоки, выполняющиеся в фоновом режиме, не ожидаются; вместо этого их выполнение приостанавливается, а их локальные объекты уничтожаются.
принципиально, это означает, что стопка этих нитей не сматывается и, таким образом, некоторые деструкторы не выполняются. В зависимости от действий, которые должны были предпринять деструкторы, ситуация могла быть такой же ужасной, как если бы программа потерпела крах или была убита. Надеюсь, ОС выпустит блокировки файлов и т. д... но вы могли бы испортить общую память, наполовину написанную файлы и тому подобное.
Итак, вы должны использовать join
или detach
?
- использовать
join
- Если вам не нужно иметь больше гибкости и готовы предоставить механизм синхронизации, чтобы дождаться завершения потока самостоятельно в этом случае вы можете использовать
detach
вы должны позвонить detach
Если вы не собираетесь ждать завершения потока с join
но поток вместо этого будет просто продолжать работать, пока это не будет сделано, а затем завершится без основного потока, ожидающего его специально.
detach
в основном освободит ресурсы, необходимые для реализации join
.
это фатальная ошибка, если объект потока заканчивает свою жизнь и ни join
, ни detach
был вызван; в этом случае terminate
is вызванный.
при отсоединении поток, это означает, что вам не нужно join()
Это перед выходом main()
.
библиотека потоков фактически будет ждать каждого такого потока ниже-main, но вы не должны заботиться о нем.
detach()
главным образом полезно, когда у вас есть задача, которая должна быть выполнена в фоновом режиме, но вы не заботитесь о его исполнении. Обычно это относится к некоторым библиотекам. Они могут молча создавать фоновый рабочий поток и отсоединять чтобы ты даже не заметил.
согласно cppreference.com:
отделяет поток выполнения от объекта потока, позволяя исполнение продолжить самостоятельно. Любые выделенные ресурсы будут освобождается после выхода потока.
после вызова detach
*this
больше не владеет потоком.
например:
std::thread my_thread([&](){XXXX});
my_thread.detach();
обратите внимание на локальную переменную: my_thread
при жизни my_thread
закончится, деструктор из std::thread
будет называться, и std::terminate()
будет вызываться в деструкторе.
но если вы используете detach()
, вы не должны использовать my_thread
больше, но если в жизни my_thread
закончено, с новым потоком ничего не произойдет.