Когда следует использовать 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 закончено, с новым потоком ничего не произойдет.