Windows для профессионалов


Атомарный доступ: семейство Inferlockect-функций - часть 5


Вызов InterlockedExchange в конце функции показывает, как вернуть переменной g_fResourceInUse значение FALSE.

Применяйте эту методику с крайней осторожностью, потому что процессорное время при спин-блокировке тратится впустую. Процессору приходится постоянно сравнивать два значения, пока одно из них не будет "волшебным образом" изменено другим потоком. Учтите - этот код подразумевает, что все потоки, использующие спин-блокировку, имеют одинаковый уровень приоритета. К тому же. Вам, наверное, придется отключить динамическое повышение приоритета этих потоков (вызовом SetProcessPriorityBoost или SetThreadPriorityBoost).

Вы должны позаботиться и о том, чтобы переменная — индикатор блокировки и данные, защищаемые такой блокировкой, не попали в одну кэш-линию (о кэш-линиях я расскажу в следующем разделе). Иначе процессор, использующий ресурс, будет конкурировать с любыми другими процессорами, которые пытаются обратиться к тому же ресурсу. А это отрицательно cкажется на быстродействии.

Избегайте спин-блокировки на однопроцессорных машинах. "Крутясь" в цикле, поток впустую транжирит драгоценное процессорное время, не давая другому потоку изменить значение неременной. Применение функции Sleep в цикле while несколько улучшает ситуацию. С ее помощью Вы можете отправлять свой поток в сон на некий случайный отрезок времени и после каждой безуспешной попытки обратиться к ресурсу увеличивать этот отрезок. Тогда потоки не будут зря отнимать процессорное время. В зависимости от ситуации вызов Sleep можно убрать или заменить на вызов SwitchToThread (эта функция в Windows 98 не доступна). Очень жаль, но, по-видимому, Вам придется действовать здесь методом проб и ошибок.

Спин-блокировка предполагает, что защищенный ресурс не бывает занят надолго. И тогда эффективнее делать так: выполнять цикл, переходить в режим ядра и ждать. Многие разработчики повторяют цикл некоторое число раз (скажем, 4000) и, если ресурс к тому времени не освободился, переводят поток в режим ядра, где он спит, ожидая освобождения ресурса (и не расходуя процессорное время).


Начало  Назад  Вперед