Ответ
В стандартной библиотеке C++ (std::thread) нет безопасного и переносимого способа принудительно завершить ("убить") один поток из другого. Попытка деструктора std::thread вызвать std::terminate, если поток еще присоединяем (joinable), приводит к аварийному завершению всей программы.
Правильные подходы в C++:
-
Кооперативная отмена через флаг: Поток должен периодически проверять флаг и завершаться самостоятельно.
#include <thread> #include <atomic> #include <chrono> std::atomic<bool> stop_flag{false}; void worker_thread() { while (!stop_flag.load()) { // Выполняем работу... std::this_thread::sleep_for(std::chrono::milliseconds(100)); } // Аккуратная очистка ресурсов } int main() { std::thread t(worker_thread); // ... stop_flag.store(true); // Запрос на остановку t.join(); // Ожидаем корректного завершения return 0; } -
Использование
std::jthread(C++20): Упрощает кооперативную отмену черезstd::stop_token.#include <thread> using namespace std::chrono_literals; int main() { std::jthread t([](std::stop_token stoken) { while (!stoken.stop_requested()) { // Работа... std::this_thread::sleep_for(100ms); } }); // ... // Деструктор jthread автоматически запросит остановку и выполнит join return 0; }
Важно: Принудительное завершение (pthread_cancel в POSIX) крайне опасно, так как может оставить мьютексы в заблокированном состоянии, не вызвать деструкторы и привести к утечкам памяти — это противоречит идиомам C++ (RAII).
Ответ 18+ 🔞
Э, слушай, тут такая тема интересная подъехала. Представь себе: ты в C++ решил потоки поразводить, а потом одного такого забияку прибить захотел. Так вот, стандартная библиотека тебе на это скажет: "Да похуй, что ты хочешь, приятель. Нет у нас такого — взять и нагло убить поток из соседнего подъезда". Серьёзно, если твой std::thread ещё жив да joinable, а ты его деструктор вызываешь — ёперный театр, вся программа накрывается медным тазом через std::terminate. Пиздец, а не выход.
Но не бзди, есть же работающие способы, не надо сразу в мантии судьи рядиться.
Нормальные человеческие подходы в C++:
-
Кооперативная отмена, или "Сам умри, когда скажут". Тут всё просто, как три копейки. Вешаешь потоку на шею атомарный флажок, а он пусть почаще на него поглядывает. Как флаг подняли — всё, пора на выход, за собой ресурсы прибрать.
#include <thread> #include <atomic> #include <chrono> std::atomic<bool> stop_flag{false}; void worker_thread() { while (!stop_flag.load()) { // Делаем свои делишки... std::this_thread::sleep_for(std::chrono::milliseconds(100)); } // Тут аккуратно всё закрываем, файлы, сокеты — красота } int main() { std::thread t(worker_thread); // ... stop_flag.store(true); // Эй, дружок, закругляйся! t.join(); // Терпеливо ждём, пока тот свои дела закончит return 0; }Чувак, это как договориться с соседом, чтобы он музыку выключил, а не вышибать ему дверь с полицией.
-
std::jthread(C++20), или "Всё за тебя сделают". Это вообще песня, если компилятор современный. Он сам, блядь, и остановку запросит, и дождётся завершения. Тебе толькоstop_tokenпроверять в цикле.#include <thread> using namespace std::chrono_literals; int main() { std::jthread t([](std::stop_token stoken) { while (!stoken.stop_requested()) { // Работаем... std::this_thread::sleep_for(100ms); } }); // ... // А тут хоть сдохни — деструктор `jthread` всё сам сделает. Волнение ебать, как удобно. return 0; }
А теперь, блядь, самое важное! Сидеть и думать: "А может, ткнуть палкой через pthread_cancel?" — это чистой воды распиздяйство. Представь: поток в этот момент мьютекс держит, память выделяет, файл пишет. Его бах — и нету. А мьютекс так и остался закрытым навеки, деструкторы не вызвались, память повисла. Это ж ядрёна вошь, а не подход! В C++ так не принято, тут уважают RAII и порядок. Так что даже не думай, доверия к такому методу — ноль ебать.