Разблокировка мьютекса, необходимого для очистки точки отмены при ожидании переменной условия? - PullRequest
0 голосов
/ 19 марта 2020

В библиотеке pthread есть понятие точек отмены. Большинство системных функций, которые могут блокировать выполнение на более длительное время (или ждать на некоторых ресурсах ...), могут быть прерваны точками отмены pthread.

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

THREAD_CLEANUP_PROC {
    UNLOCK(mutex) // Is this unlock required?
}

THREAD_PROC {
    SET THREAD_CLEANUP = THREAD_CLEANUP_PROC
    LOOP {
        LOCK(mutex)
        WHILE (condition == false) {
            condition.WAIT(mutex) // wait interrupted, cancel point is called
        }
        // ... we have the lock
        UNLOCK(mutex)
        condition.NOTIFY_ALL()

        read(descriptor); // wait for some data on a file descriptor while lock is not acquired
    }
}

Если кто-то отменяет поток (pthread_cancel ()) во время ожидания переменной условия, документация о pthread_cond_wait говорит, что поток разблокируется при получении блокировки и начинает выполнение обработчика очистки до завершения потока.

Верно ли, что обработчик очистки теперь отвечает за разблокировку этой блокировки (мьютекса)? Что если - как в моем примере - есть другой метод блокировки, такой как read, который блокирует при ожидании данных, но без получения блокировки? В этом случае read также разблокируется, и обработчик очистки вызывается, как и раньше. Только на этот раз обработчик очистки не должен разблокировать мьютекс. Я прав. Если да, то как лучше всего справиться с этой ситуацией? Существуют ли общие понятия, которым нужно следовать?

1 Ответ

2 голосов
/ 21 марта 2020

Тема отмены грязная. Вообще говоря, вы не должны этого делать.

В библиотеке pthread есть понятие точек отмены.

Да.

Большинство системных функций, которые могут блокировать выполнение на более длительное время (или ждать на некоторых ресурсах ...), могут быть прерваны точками отмены pthread.

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

Если кто-то отменяет поток ( pthread_cancel ()) во время ожидания условной переменной в документации о pthread_cond_wait говорится, что поток разблокируется при получении блокировки и начинает выполнение обработчика очистки до завершения потока.

Да, при условии что поток имеет «отложенный» тип отмены.

Верно ли, что обработчик очистки теперь отвечает за разблокировку этой блокировки (мьютекса)?

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

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

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

Если так, как лучше всего справиться с этой ситуацией?

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

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

...