Мне не нужно правильно завершать поток или заставлять его отвечать на команду «завершить». Я заинтересован в принудительном завершении потока с использованием чистого C ++ 11.
c++
multithreading
c++11
Александр V
источник
источник
Ответы:
Вы можете позвонить
std::terminate()
из любого потока, и поток, на который вы ссылаетесь, принудительно завершится.Вы можете организовать
~thread()
выполнение на объекте целевого потока без вмешательстваjoin()
илиdetach()
на этом объекте. Это будет иметь тот же эффект, что и вариант 1.Вы можете создать исключение, которое имеет деструктор, который генерирует исключение. А затем сделайте так, чтобы целевой поток генерировал это исключение, когда он должен быть принудительно завершен. Сложность в том, чтобы заставить целевой поток генерировать это исключение.
Варианты 1 и 2 не приводят к утечке ресурсов внутри процесса, но завершают каждый поток.
Вариант 3, вероятно, приведет к утечке ресурсов, но он частично совместим, поскольку целевой поток должен дать согласие на создание исключения.
В C ++ 11 нет переносимого способа (о котором я знаю) для некоперативного уничтожения одного потока в многопоточной программе (то есть без уничтожения всех потоков). Не было мотивации создавать такую функцию.
A
std::thread
может иметь эту функцию-член:Возможно, вы сможете использовать это, чтобы вызвать зависимую от ОС функцию, чтобы делать то, что вы хотите. Например, в ОС Apple эта функция существует и
native_handle_type
является файломpthread_t
. Если вы добьетесь успеха, у вас может произойти утечка ресурсов.источник
std::terminate
не вызывает статические деструкторы и не очищает выходные буферы, поэтому порядок, в котором освобождаются ресурсы, не определен четко, и у вас нет никакой гарантии, что какие-либо из ваших данных будут видны пользователю или записаны в постоянное хранилище, или даже последовательный и полный.exit()
илиabort()
с таким же общим эффектом.Ответ @Howard Hinnant правильный и исчерпывающий. Но это может быть неправильно понято, если оно будет прочитано слишком быстро, потому что
std::terminate()
(весь процесс) имеет то же имя, что и «завершение», которое имел в виду @AlexanderVX (1 поток).Резюме: «завершить 1 поток + принудительно (целевой поток не взаимодействует) + чистый C ++ 11 = нет».
источник
std::terminate()
ответ похож на классическую озорную историю про джиннов; он выполняет все в желании ОП до буквы, хотя, вероятно, не так, как он имел в виду . Сдержанный юмор заставил меня улыбнуться. :-)Этот вопрос на самом деле имеет более глубокий характер, и хорошее понимание концепций многопоточности в целом даст вам представление об этой теме. На самом деле не существует какого-либо языка или операционной системы, которые предоставляли бы вам средства для асинхронного внезапного завершения потока без предупреждения, чтобы не использовать их. И все эти среды выполнения настоятельно рекомендуют разработчикам или даже требуют создания многопоточных приложений на основе кооперативного или синхронного завершения потоков. Причина таких общих решений и советов в том, что все они построены на основе одной и той же общей модели многопоточности.
Давайте сравним концепции многопроцессорности и многопоточности, чтобы лучше понять преимущества и ограничения второго.
Многопроцессорность предполагает разделение всей среды выполнения на набор полностью изолированных процессов, управляемых операционной системой. Процесс включает и изолирует состояние среды выполнения, включая локальную память процесса и данные внутри нее, а также все системные ресурсы, такие как файлы, сокеты, объекты синхронизации. Изоляция - критически важная характеристика процесса, поскольку она ограничивает распространение неисправностей за пределы процесса. Другими словами, ни один процесс не может повлиять на согласованность любого другого процесса в системе. То же самое верно и для поведения процесса, но в менее ограниченном и более размытом виде. В такой среде любой процесс может быть остановлен в любой «произвольный» момент, потому что, во-первых, каждый процесс изолирован, во-вторых,
Напротив, многопоточность предполагает выполнение нескольких потоков в одном процессе. Но все эти потоки используют один и тот же изолирующий блок, и операционная система не контролирует внутреннее состояние процесса. В результате любой поток может изменить состояние глобального процесса, а также повредить его. В то же время точки, в которых состояние потока, как известно, безопасно для уничтожения потока, полностью зависят от логики приложения и неизвестны ни операционной системе, ни среде выполнения языка программирования. В результате завершение потока в произвольный момент означает его уничтожение в произвольной точке его пути выполнения и может легко привести к повреждению данных всего процесса, утечке памяти и обработчиков,
Из-за этого общий подход заключается в том, чтобы заставить разработчиков реализовать синхронное или совместное завершение потока, когда один поток может запросить завершение другого потока, а другой поток в четко определенной точке может проверить этот запрос и запустить процедуру завершения из четко определенного состояния. с высвобождением всех глобальных общесистемных ресурсов и локальных общесистемных ресурсов безопасным и последовательным способом.
источник
Советы по использованию ОС-зависимой функции для завершения потока C ++:
std::thread::native_handle()
только может получить допустимый собственный тип дескриптора потока до вызоваjoin()
илиdetach()
. После этогоnative_handle()
вернет 0 -pthread_cancel()
будет дамп.Чтобы эффективно вызвать функцию завершения собственного потока (например
pthread_cancel()
), вам необходимо сохранить собственный дескриптор перед вызовомstd::thread::join()
илиstd::thread::detach()
. Так что у вашего родного терминатора всегда есть допустимый родной дескриптор для использования.Дополнительные объяснения см. По адресу : http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
источник
Я предполагаю, что поток, который нужно убить, находится либо в любом режиме ожидания, либо выполняет тяжелую работу. Я бы предложил использовать «наивный» способ.
Определите какое-нибудь глобальное логическое значение:
Поместите следующий код (или аналогичный) в несколько ключевых точек таким образом, чтобы все функции в стеке вызовов возвращались до тех пор, пока поток не завершится естественным образом:
Затем, чтобы остановить поток из другого (основного) потока:
источник