Шаг 298.
Модели потоков. Дополнительные механизмы синхронизации. Защищенный доступ к переменным

    На этом шаге мы рассмотрим функции, реализующие такой доступ.

    Часто возникает необходимость совершения операций над разделяемыми между потоками 32-разрядными переменными. Для упрощения решения этой задачи Windows API предоставляет функции защищенного доступа к переменным (interlocked variable access), не требующие дополнительных (и более сложных) механизмов синхронизации. Переменные в этих функциях должны быть выровнены по границе 32-разрядного слова. Применительно к Delphi это означает, что если переменная объявлена внутри записи (record), то эта запись не должна быть упакованной (packed) и при ее объявлении должна быть активна директива компилятора {$А+}. Несоблюдение этого требования может привести к возникновению ошибок на многопроцессорных конфигурациях, что иллюстрируется приведенным ниже примером.

type
  TPackedRecord = packed record
    A: Byte;
    B: Integer;
  end;   
// TPackedRecord.B нельзя использовать в функциях InterlockedXXX

  TNotPackedRecord = record
    A: Byte;
    B: Integer;
  end;

{$A-}
var
  A1: TNotPackedRecord;
// A1.B нельзя использовать в функциях InterlockedXXX
  I: Integer
// I можно использовать в функциях InterlockedXXX, так как 
// переменные в Delphi всегда выравниваются по границе слова, 
// независимо от состояния директивы компилятора $A

{$A+}
var
  A2: TNotPackedRecord;
// A2.B можно использовать в функциях InterlockedXXX

    Далее мы рассмотрим функции для защищенного доступа к разделяемым между потоками 32-разрядным переменным, предоставляемые Windows API.

function InterlockedIncrement(
var Addend: Integer 
): Integer; stdcall;

    Функция увеличивает переменную Addend на 1. Возвращаемое значение зависит от операционной системы.

function InterlockedDecrement(
var Addend: Integer 
): Integer; stdcall;

    Функция уменьшает переменную Addend на 1. Возвращаемое значение аналогично возвращаемому значению функции InterlockedIncrement.

function InterlockedExchange(
  var Target: Integer;
  Value: Integer 
): Integer; stdcall;

    Функция записывает в переменную Target значение Value и возвращает предыдущее значение переменной Target.

    Следующие функциидля выполнения требуют Windows 98 или Windows NT 4.0 и выше.

function InterlockedCompareExchange(
  var Destination: Pointer;
  Exchange: Pointer;
  Comperand: Pointer 
): Pointer; stdcall;

    Функция сравнивает значения Destination и Comperand. Если они совпадают, значение Exchange записывается в Destination. Функция возвращает начальное значение Destination.

function InterlockedExchangeAdd(
  Addend: PLongint;
  Value: Longint 
): Longint; stdcall;

    Функция добавляет к переменной, на которую указывает Addend, значение Value и возвращает начальное значение Addend.

    На следующем шаге мы рассмотрим взаимную блокировку.




Предыдущий шаг Содержание Следующий шаг