Подтвердить что ты не робот

Как завершить поток в С++ 11?

Мне не нужно корректно завершать поток или отвечать на команду "завершить". Я заинтересован в прекращении потока с использованием чистого С++ 11.

4b9b3361

Ответ 1

  • Вы можете вызвать std::terminate() из любого потока, и поток, на который вы ссылаетесь, сильно закончится.

  • Вы можете организовать ~thread() для выполнения объекта целевого потока без промежуточного join() и detach() на этом объекте. Это будет иметь тот же эффект, что и вариант 1.

  • Вы можете создать исключение, которое имеет деструктор, который генерирует исключение. А затем упорядочьте целевой поток, чтобы выбросить это исключение, когда оно должно быть принудительно прекращено. Трудная часть этого вопроса - получить целевой поток, чтобы выбросить это исключение.

Варианты 1 и 2 не просачивают ресурсы внутри процесса, но завершают каждый поток.

Вариант 3, вероятно, будет утечка ресурсов, но частично совместим с тем, что целевой поток должен согласиться с тем, чтобы исключить исключение.

В С++ 11 (что я знаю) нет переносимого способа, чтобы неработоспособно убить один поток в многопоточной программе (т.е. без уничтожения всех потоков). Не было никакой мотивации для разработки такой функции.

A std::thread может иметь эту функцию-член:

native_handle_type native_handle();

Возможно, вы сможете использовать это, чтобы вызвать функцию, зависящую от ОС, чтобы делать то, что вы хотите. Например, в Apple OS эта функция существует, а native_handle_type - pthread_t. Если вы успешны, вы, скорее всего, будете утечка ресурсов.

Ответ 2

@Howard Hinnant ответ правильный и всеобъемлющий. Но это может быть неправильно понято, если он читает слишком быстро, потому что std::terminate() (весь процесс) имеет то же имя, что и "завершение", которое имел в виду @AlexanderVX (1 поток).

Сводка: "завершать 1 поток + принудительно (целевой поток не взаимодействует) + чистый С++ 11 = нет."

Ответ 3

Этот вопрос на самом деле имеет более глубокий характер и хорошее понимание концепций многопоточности в целом предоставит вам представление об этой теме. На самом деле не существует ни языка, ни какой-либо операционной системы, которая предоставит вам возможности для асинхронного прерывания потока без предупреждения, чтобы не использовать их. И все эти среды исполнения настоятельно советуют разработчику или даже требуют создания многопоточных приложений на основе совместной или синхронной прерывания потока. Причиной этих общих решений и советов является то, что все они построены на основе одной и той же общей многопотоковой модели.

Давайте сравним понятия многопроцессорности и многопоточности, чтобы лучше понять преимущества и ограничения второго.

Многопроцессорность предполагает разделение всей среды исполнения на множество полностью изолированных процессов, управляемых операционной системой. Процесс включает и изолирует состояние среды выполнения, включая локальную память процесса и данных внутри него и всех системных ресурсов, таких как файлы, сокеты, объекты синхронизации. Изоляция является критически важной характеристикой процесса, поскольку она ограничивает распространение ошибок границами процесса. Другими словами, ни один процесс не может повлиять на согласованность любого другого процесса в системе. То же самое верно для поведения процесса, но в менее ограниченном и более размытом виде. В такой среде любой процесс может быть убит в любой "произвольный" момент, потому что, во-первых, каждый процесс изолирован, во-вторых, операционная система обладает полными знаниями обо всех ресурсах, используемых процессом, и может выпустить все из них без утечки, и, наконец, процесс будет убит по ОС не в любой момент, а в количестве четко определенных точек, где состояние процесса хорошо известно.

Напротив, многопоточность предполагает выполнение нескольких потоков в одном процессе. Но все эти потоки разделяют одну и ту же единицу изоляции, и нет никакого управления операционной системой внутреннего состояния процесса. В результате любой поток может изменить состояние глобального процесса, а также испортить его. В то же время точки, в которых состояние потока хорошо известно, что безопасно убить поток, полностью зависят от логики приложения и не известны ни для операционной системы, ни для языка программирования. В результате прерывание потока в произвольный момент означает его уничтожение в произвольной точке его пути выполнения и может легко привести к обрыву данных в масштабе всей организации, утечке памяти и ручек, утечке потоков и запорным блокам и другим примитивам синхронизации внутри процесса, закрытое состояние, предотвращающее прохождение других потоков.

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

Ответ 4

Советы по использованию OS-зависимой функции для завершения потока C++:

  1. std::thread::native_handle() может получить потоки действительного собственного типа дескриптора перед вызовом join() или detach(). После этого native_handle() возвращает 0 - pthread_cancel() будет выполнять coredump.

  2. Чтобы эффективно вызывать собственную функцию завершения потока (например, pthread_cancel), вам нужно сохранить собственный дескриптор перед вызовом std::thread::join() или std::thread::detach(). Так что ваш родной терминатор всегда имеет действительный собственный дескриптор для использования.

Дополнительные пояснения можно найти по адресу: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread.

Ответ 5

Я предполагаю, что поток, который нужно убить, находится либо в любом режиме ожидания, либо выполняет какую-то тяжелую работу. Я бы предложил использовать "наивный" способ.

Определите некоторые глобальные логические:

std::atomic_bool stop_thread_1 = false;

Поместите следующий код (или аналогичный) в несколько ключевых точек таким образом, чтобы он вызывал возврат всех функций в стеке вызовов до естественного завершения потока:

if (stop_thread_1)
    return;

Затем, чтобы остановить поток из другого (основного) потока:

stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(this can be when starting the thread instead)