Как я могу предоставить право собственности на мьютекс определенному потоку?

Представьте, что у меня заблокирован мьютекс. Существует неограниченное количество других потоков, ожидающих блокировки мьютекса. Когда я разблокирую мьютекс, один из этих потоков будет выбран для входа в критическую секцию. Однако я не могу контролировать, какой именно. Что, если я хочу, чтобы конкретная ветка попала в критическую секцию?

Я почти уверен, что это невозможно сделать с помощью мьютекса POSIX, однако могу ли я имитировать поведение с помощью другого объекта (ов) синхронизации?


person Martin Sustrik    schedule 03.10.2012    source источник
comment
Единственная гарантия, которую вы получите, - это справедливость некоторых механизмов, но ни один из них не имеет необходимых вам функций. Разве вы не можете изменить свой алгоритм, чтобы он не зависел от того, какой поток проходит первым? Возможно, если вы объясните, что делаете, мы сможем что-нибудь придумать.   -  person Tudor    schedule 03.10.2012
comment
Это необходимо для предотвращения тупиковой ситуации: я нахожусь в критическом разделе и собираюсь заблокировать другой критический раздел. Однако я знаю, что есть еще один поток, у которого заблокирована последняя CS, и который пытается заблокировать предыдущую CS. Чтобы предотвратить взаимоблокировку, мне нужно уведомить другой поток, который должен отменить попытку заблокировать предыдущий CS.   -  person Martin Sustrik    schedule 03.10.2012
comment
Разве каждый поток не может получить все блокировки в одном и том же порядке? Тогда у вас не будет проблем с тупиком.   -  person Tudor    schedule 03.10.2012
comment
Нет, не может. Кстати, см. Жизнеспособное - хотя и не очень эффективное - решение ниже.   -  person Martin Sustrik    schedule 03.10.2012


Ответы (1)


Для этого вы можете использовать мьютекс, переменную условия и идентификатор потока.

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

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


Другой вариант - использовать сигналы, отправленные в конкретный поток. Допустим, мы используем SIGRTMIN для этой цели. Во-первых, все потоки блокируют этот сигнал в начале, так что сигнал становится ожидающим и не теряется, когда поток его не ждет. Когда поток хочет заблокировать мьютекс, он сначала вызывает sigwait(), который атомарно разблокирует SIGRTMIN и ждет его или доставляет уже ожидающий. Как только поток получил сигнал, он может продолжить и заблокировать мьютекс. Сигнальный поток использует pthread_kill(target_thread_id, SIGRTMIN) для пробуждения определенного потока.

person Maxim Egorushkin    schedule 03.10.2012
comment
Ага. Я так и сделал. Меня беспокоили накладные расходы на производительность, связанные с случайным пропуском потоков в критическую секцию и проверкой правильности этого потока. Хотя на данный момент я не могу придумать ничего лучше. - person Martin Sustrik; 03.10.2012
comment
@MartinSustrik Я добавил альтернативный метод. - person Maxim Egorushkin; 04.10.2012