Какой правильный объект синхронизации потоков в Windows позволяет потоку ждать, пока другой поток не разблокирует его? - PullRequest
1 голос
/ 22 ноября 2011

У меня есть приложение Delphi, работающее под Windows, которое необходимо заблокировать, пока другой поток не доставит данные.Другими словами, мне нужно дождаться объекта синхронизации, который из определенного потока я могу перевести в не сигнализированное состояние , как если бы другой поток владел объектом, поэтому при вызове WaitFor () поток блокируется, пока один из других потоков не разблокирует его (существует более одного потенциального потока, который может разблокировать , и заранее неизвестно, какой из них).Обратите внимание, что все потоки имеют доступ к общей области данных, поэтому доступ к общему объекту синхронизации не является проблемой.

Я думал, События были правильным выбором, пока я не прочитал этот неприятный постРаймонд Чен (Raymond Chen) о проблемах с PulseEvent ():

http://blogs.msdn.com/b/oldnewthing/archive/2005/01/05/346888.aspx

Какая правильная техника синхронизации позволяет достичь этого результата?Если у вас есть ссылка на пример Delphi или C / C ++, это было бы замечательно.

Ответы [ 2 ]

2 голосов
/ 22 ноября 2011

События в порядке, просто не используйте PulseEvent.Microsoft не только безнадежно испортила реализацию, но и усложнила ее использование в условиях гонки.Если событие происходит непосредственно перед тем, как поток блокирует событие, событие будет потеряно.Вместо этого используйте события ручного сброса.

Для блокировки:

B1) Установите для блокировки событие.

B2) Проверьте, чтобы событие еще не произошлои убедитесь, что хотите заблокировать это.Если необходимо, поместите событие в общую структуру данных, чтобы разбудившие нас потоки заметили его.

B3) Блокировать событие.

Пробудить:

W1) Обновитьобщие данные, чтобы отразить тот факт, что событие произошло.

W2) Разблокировать событие.При необходимости просмотрите общую структуру данных и разблокируйте все события, связанные с тем, что только что произошло.

Здесь нет условия гонки.Если событие происходит после B1 или B2, но до B3, блок в B3 фактически не будет блокироваться, потому что W2 разблокирует его.Если событие уже произошло до W1, поток никогда не заблокируется, потому что B2 увидит влияние W1, и мы никогда не доберемся до B3.

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

0 голосов
/ 11 мая 2017

Просто используйте события автоматического сброса. Смотрите параметры функции CreateEvent. Вам понадобится одно событие для каждого потока, которого нужно ждать. Просто вызовите SetEvent, и никаких других функций, таких как PulseEvent или ResetEvent. WaitFor автоматически сбросит событие. Если событие уже было установлено перед вызовом WaitFor, оно немедленно вернется, сбросив событие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...