Использование join и detach c++

Имеется следующий код:

class MyClass {
public:
    void doWork() {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        std::cout << "ID потока: " << std::this_thread::get_id() << "\tdoWork started\t" << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        std::cout << "ID потока: " << std::this_thread::get_id() << "\tdoWork stopped\t" << "\n";
    };

    void doWork2(int a) {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        std::cout << "ID потока: " << std::this_thread::get_id() << "\tdoWork2 started\t" << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        std::cout << "Значение параметра doWork2 " << a;
        std::cout << "ID потока: " << std::this_thread::get_id() << "\tdoWork2 stopped\t" << "\n";
    };

    int sum(int a, int b) {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        std::cout << "ID потока: " << std::this_thread::get_id() << "\tsum started\t" << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        std::cout << "ID потока: " << std::this_thread::get_id() << "\tsum stopped\t" << "\n";
        return a + b;
    }
};

int main() {
    setlocale(LC_ALL, "ru");

    MyClass class1;
    std::thread th1(&MyClass::doWork, class1);

    for (int i = 0; i < 3; ++i) {
        std::cout << "ID потока: " << std::this_thread::get_id() << "\tmain work\t" << i << "\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    };

    th1.join();
    return 0;
}

Я ведь правильно понимаю, что join нужен для того, чтобы если main завершился раньше, программа дождалась выполнения созданного th1 потока?

Также не очень понимаю случаи, когда нужен detach.

detach же просто "отправит поток в свободное плавание", как тогда забрать из него результат и в каких кейсах применять его вместо join?

Спасибо


Ответы (1 шт):

Автор решения: user7860670

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

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

В С++20 появлися класс std::jthread, который имеет встроенный механизм оповещения о необходимости завершения потока и сам вызывает join в деструкторе.

→ Ссылка