Мені не потрібно правильно завершувати потік або змушувати його реагувати на команду "завершити". Мені цікаво завершити потік насильно за допомогою чистого C ++ 11.
Мені не потрібно правильно завершувати потік або змушувати його реагувати на команду "завершити". Мені цікаво завершити потік насильно за допомогою чистого C ++ 11.
Відповіді:
Ви можете зателефонувати std::terminate()
з будь-якої нитки, і потік, на який ви посилаєтесь, насильно закінчиться.
Ви можете домовитись ~thread()
виконання на об'єкті цільової нитки, не втручаючись join()
ні detach()
на цьому об'єкті. Це матиме такий же ефект, як і варіант 1.
Ви можете створити виняток, який містить деструктор, який видає виняток. А потім домовтеся, щоб цільовий потік кинув цей виняток, коли його потрібно насильно припинити. Хитра частина цього - отримання цільової нитки, щоб кинути цей виняток.
Варіанти 1 і 2 не протікають у внутріпроцесових ресурсах, але вони припиняють кожен потік.
Варіант 3, ймовірно, просочить ресурси, але частково співпрацює в тому, що цільовий потік повинен погодитися викинути виняток.
У C ++ 11 (про що я знаю) немає портативного способу беззаконного вбивання однієї нитки в багатопотоковій програмі (тобто, не вбиваючи всіх потоків). Не було мотивації розробити таку особливість.
A std::thread
може мати цю функцію члена:
native_handle_type native_handle();
Ви можете використовувати це для виклику функції, залежної від ОС, і робити те, що ви хочете. Наприклад, в ОС Apple, ця функція існує і native_handle_type
є pthread_t
. Якщо ви досягли успіху, ви, швидше за все, просочите ресурси.
std::terminate
не викликає статичних деструкторів і не змиває вихідні буфери, тому порядок випуску ресурсів не є чітко визначеним, і ви не маєте жодної гарантії, що будь-які ваші дані будуть видимі користувачеві або записані в постійне зберігання, або навіть послідовний і повний.
exit()
або abort()
з однаковим загальним ефектом.
Відповідь Говарда Гіннанта є правильною та вичерпною. Але це може бути неправильно зрозуміти, якщо він буде прочитаний занадто швидко, тому що std::terminate()
(весь процес) має те саме ім'я, що і "закінчується", про який пам'ятав @AlexanderVX (1 тема).
Підсумок: "завершити 1 потік + насильно (цільовий потік не співпрацює) + чистий C ++ 11 = Ні в якому разі."
std::terminate()
відповідь - це як класична неслухняна історія Джинна; він виконує все в бажанні ОП до листа, хоча, мабуть, не так, як він мав на увазі . Занижений гумор змусив мене посміхнутися. :-)
Це питання насправді має більш глибокий характер і добре розуміння багатопотокових концепцій взагалі дасть вам зрозуміти цю тему. Насправді немає жодної мови чи будь-якої операційної системи, яка б надала вам засоби для асинхронного різкого припинення потоку без попередження про їх використання. І всі ці середовища виконання настійно радять розробнику або навіть вимагають будувати багатопотокові програми на основі спільного або синхронного завершення потоку. Причиною цих загальних рішень та порад є те, що всі вони побудовані на основі тієї ж загальної багатопотокової моделі.
Порівняємо багатопроцесорні та багатопотокові концепції, щоб краще зрозуміти переваги та обмеження другого.
Багатопроцесорна система передбачає розщеплення всього середовища виконання на безліч повністю ізольованих процесів, керованих операційною системою. Процес включає і ізолює стан середовища виконання, включаючи локальну пам'ять процесу та даних всередині нього та всі системні ресурси, такі як файли, сокети, об'єкти синхронізації. Ізоляція є критично важливою характеристикою процесу, оскільки вона обмежує поширення несправностей за межами процесу. Іншими словами, жоден процес не може впливати на послідовність будь-якого іншого процесу в системі. Те саме стосується поведінки процесу, але менш обмеженим та більш розмитим способом. У такому середовищі будь-який процес може бути вбитий у будь-який "довільний" момент, оскільки, по-перше, кожен процес ізольований, по-друге,
На відміну від цього, багатопотоковість передбачає запуск декількох потоків в одному процесі. Але всі ці потоки мають одне і те ж ізоляційне вікно, і немає ніякого контролю операційною системою внутрішнього стану процесу. В результаті будь-яка нитка здатна змінити глобальний стан процесу, а також зіпсувати його. У той же момент точки, в яких стан потоку, як відомо, є безпечним для вбивства потоку, повністю залежать від логіки програми і не відомі ні для операційної системи, ні для часу програмування мови програмування. В результаті припинення потоку в довільний момент означає вбивство його в довільній точці шляху його виконання і може легко призвести до пошкодження даних, пам’яті та витоку даних,
Завдяки цьому загальний підхід полягає в тому, щоб змусити розробників впроваджувати синхронне або спільне завершення потоку, коли один потік може вимагати закінчення потоку іншого потоку, а інший потік у чітко визначеній точці може перевірити цей запит і запустити процедуру відключення з чітко визначеного стану із звільненням усіх глобальних загальносистемних ресурсів та локальних ресурсів, що охоплюють всі процеси, безпечним та послідовним.
Поради щодо використання функції, що залежить від ОС, для завершення потоку C ++:
std::thread::native_handle()
тільки може отримати дійсний власний тип ручки Нитки перед викликом join()
або detach()
. Після цього native_handle()
повертається 0 - pthread_cancel()
буде coredump.
Для того, щоб ефективно називати рідну функцію завершення нитки (наприклад pthread_cancel()
), ви повинні зберегти рідну ручку перед викликом std::thread::join()
або std::thread::detach()
. Таким чином, щоб ваш рідний термінатор завжди мав використовувати дійсну ручку.
Більше пояснень див. На веб-сторінці: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .
Я думаю, що нитка, яку потрібно вбити, знаходиться або в будь-якому режимі очікування, або виконує якусь важку роботу. Я б запропонував використовувати «наївний» спосіб.
Визначте деякі глобальні булеві:
std::atomic_bool stop_thread_1 = false;
Поставте наступний код (або подібний) у декілька ключових моментів таким чином, що це призведе до повернення всіх функцій у стеку викликів, поки потік природним чином не закінчиться:
if (stop_thread_1)
return;
Потім для зупинки потоку з іншої (головної) нитки:
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)