Уничтожение pthread в ожидании переменной условия

У меня есть pthread в ожидании переменной условия с использованием pthread_cond_wait. Он ожидает данных из структуры очереди, заполненной другим потоком. Я хочу убить эту тему, желательно без pthread_kill. В Linux и WinPthreads делает pthread_cancel(); pthread_join() достаточно, чтобы убить его. Однако на OS X это висит на вызове pthread_join. Какие-либо предложения?

3 ответа

Решение

Есть ли у вас доступ к очереди и управление схемой объектов для объектов в очереди? Если это так, определите тип объекта очереди, который при выводе из очереди дает команду потоку, обрабатывающему элемент, корректно завершить работу.

Теперь, чтобы закрыть эти потоки, просто отправьте несколько таких объектов "выхода" в HEAD очереди, которая соответствует количеству потоков, обслуживающих очередь, и присоединитесь к потокам.

Это выглядит намного чище, чем "ядерная опция" в pthread_cancel/kill.

pthread_cancel должен разбудить поток, который заблокирован в pthread_cond_wait --- это один из обязательных пунктов отмены. Если это не работает, значит что-то не так.

Первое, что нужно проверить, это то, что отмена действительно включена в целевом потоке - явно вызвать pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldstate) на целевой нити, чтобы убедиться. Если это не сработает, то отмена отменяется на вашей платформе, и вам придется прибегнуть к альтернативным вариантам, таким как установка флага "пожалуйста, прекратите сейчас" и сигнализация переменной условия.

Не используйте асинхронную отмену, если вы действительно не знаете, что делаете - это может вызвать отмену в середине любой операции (например, в середине установки фрейма стека вызова функции или запуска деструктора), и, таким образом, может оставить Ваш код в полностью несовместимом состоянии. Написание кода async-cancel-safe затруднительно.

между прочим pthread_kill не убивает поток --- он посылает сигнал ему.

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

Это может быть потому, что поток может не отвечать на отмену, пока он находится в состоянии ожидания (или вообще).

POSIX.1c-2004 (v6) заявляет:

Состояние отмены и тип всех вновь создаваемых потоков, включая поток, в котором main() был впервые вызван, должны быть PTHREAD_CANCEL_ENABLE а также PTHREAD_CANCEL_DEFERRED соответственно.

Это означает, что вы должны явно проверить отмену с pthread_testcancel(),

Другой вариант - установить тип отмены потоков на PTHREAD_CANCEL_ASYNCHRONOUS когда он впервые начинает работать, что-то вроде:

int junk;
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &junk);
std::cout
    << ((junk==PTHREAD_CANCEL_DEFERRED) ? "Was deferred" : "Wasn't")
    << std::endl;

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

Отмена - это запрос к целевому потоку, который он может игнорировать, если пожелает, в отличие от гораздо большего зла pthread_kill(), Я большой сторонник того, чтобы позволить потокам управлять их собственными жизнями, так как я обнаружил, что это неизменно приводит к меньшему количеству проблем параллелизма.

В стороне: На самом деле, будучи купленным в очень ранних выпусках pthreads, даже до интеграции в DCE, я все еще обнаруживаю, что просто использую глобальную переменную для каждого потока, указывающую, когда он должен выйти, наряду с ручным пинком мьютексов или условных переменных, чтобы разбудить темы вверх. Я думаю, что я должен обновить свои методы (или я хотел бы, если бы я мог видеть явное преимущество).:-)

Другие вопросы по тегам