Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows


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


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

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

Последняя пара Interlocked-функций выглядит так:

PVOID InterlockedCompareExchange( PLONG pIOestination, LONG lExchange, LONG lComparand);

PVOID InterlockedCompareExchangePointer( PVOID* ppvDestination, PVOID pvExchange, PVOID pvComparand);

Они выполняют операцию сравнения и присвоения на уровне атомарного досту па. В 32-разрядном приложении обе функции работают с 32-разрядными значения ми, но в 64-разрядном приложении InterlockedCompareExchange используется для 32 разрядных значений, a InterlockedCompareExcbangePointer - для 64-разрядных. Вот как они действуют, если представить это в псевдокоде.

LONG InterlockedCompareExchange(PLONG plDestination, LONG lExchange, LONG lComparand) {

LONG lRet = *plDestination;
// исходное значение

if (*plDestination == lComparand)
*plDestination = lExchange;


return(lRet); }

Функция сравнивает текущее значение переменной типа LONG (на которую ука зывает параметр plDestination) со значением, передаваемым в параметре lComparand. Если значения совпадают, *plDestination получает значение параметра lExchange; в ином случае *pUDestination остается без изменений. Функция возвращает исходное значение *plDestination. И не забывайте, что все эти действия выполняются как еди ная атомарная операция.

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

Interlocked-функции можно также использовать в потоках различных процессов для синхронизации доступа к переменной, которая находится в разделяемой облас ти памяти, например в проекции файла. (Правильное применение Interlocked-функ ций демонстрирует несколько программ-примеров из главы 9 )

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

LONG Interlockedlncrernent(PLONG plAddend);

LONG IntorlockedDecrcment(PLONG plAddend);

InterlockedExchangeAdd полностью заменяет обе эти устаревшие функции. Новая функция умеет добавлять и вычитать произвольные значения, а функции Interlocked Increment и InterlockedDecrement увеличивают и уменьшают значения только на 1.




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