# Threads joining А вы уже заметили, что в [предыдущих](./race_condition.md) заметках я использую `std::jthread` из C++20 вместо `std::thread`? И зачем? А все очень просто: деструктор `std::thread` дурной. Везде, где может начать вызываться деструктор `std::thread`, нужно втыкать ```C++ // std::thread t1; if (t1.joinable()) { // Если вы не уверены в богатой жизненной истории // объекта t1, обязательно выполняйте эту проверку t1.join(); // или t1.detach() } ``` Чтобы ознаменовать свое желание (или нежелание) дожидаться окончания выполнения потока. Иначе деструктор потока повалит вашу программу, вызвав `std::terminate`. Очень удобно и очень по RAII-шному, неправда ли? Нет, конечно, совсем везде втыкать не надо. Если вы знаете, что кто-то другой уже выполнил это заклинание, или содержимое объекта `std::thread` переместили в другой объект (`t2 = std::move(t1)`). И тем более не надо просто так втыкать этот код, обращающийся к одному и тому же объекту `std::thread` из разных потоков. Иначе — race condition. Надо синхронизировать. И, конечно же, убедитесь что этот код ни в коем случае не будет выполняться параллельно с вызовом деструктора `t1`; Деструктор тоже вызывает `joinable`, а это опять race condition. Собираетесь сделать обертку над `std::thread`, чтобы вызывать `join` в ее деструкторе? Спешу порадовать: `join`/`detach` кидают исключения. Со всеми вытекающими [проблемами](../runtime/noexcept.md). Здорово, да? Поэтому в примерах был и будет `std::jthread`. Его деструктор сам выполняет `join` и снимает хотя бы часть головной боли. А если вас `join` не устраивает, не хотите ждать и пользуетесь `detach`... Ну что ж. Право ваше. Только помните, что все потоки резко и внезапно помрут, когда закончится `main`. ## Полезные ссылки 1. https://en.cppreference.com/w/cpp/thread/thread 2. https://en.cppreference.com/w/cpp/thread/jthread