суббота, 22 мая 2010 г.

Поток, ожидающий объекта синхронизации, может просто его проспать

Это перевод A thread waiting on a synchronization object could be caught napping. Автор: Реймонд Чен.

Если у вас есть объект синхронизации, например, семафор, и 2 потока, ожидающих этот семафор, и если потом вы отпускаете два токена семафора в единственном вызове ReleaseSemaphore, то вы ожидаете, что каждый из ожидающих потоков проснётся, каждый поток получит по одному токену. И, действительно, большую часть времени именно так и бывает.

Вспомните, из нашей предыдущей дискуссии, что поток в ожидающем состоянии может быть временно взят для обслуживания APC режима ядра и из-за этого пропустить смену статуса. Ровно та же вещь может случится с потоком, ожидающим семафор. Если вызов ReleaseSemaphore произойдёт, пока поток угнали для обслуживания APC, то он не запросит у семафора для себя токен немедленно, но попробует его взять, после завершения обслуживания APC, когда поток снова вернётся в состояние ожидания.

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

К счастью, случаи, когда у вас есть соревнование за токены семафора, являются разновидностями сценария producer/consumer, в которых не имеет значения, кто именно возьмёт токены семафора - главное, чтобы кто-то это вообще сделал.

Упражнение: если у вас есть несколько потоков, ожидающих событие с автосбросом (auto-reset event), и событие переходит в сигнальное состояние, можете ли вы предугадать, какой поток проснётся?

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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