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

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

   
Часто возникает необходимость совершения операций над разделяемыми между потоками 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. Возвращаемое значение зависит от операционной системы.

  • Windows 98, Windows NT 4.0 и выше - возвращается новое значение переменной Addend.
  • Windows 95, Windows NT 3.51:
    • если после изменения Addend < 0, то возвращается отрицательное число, не обязательно равное Addend;
    • если Addend = 0, возвращается 0;
    • если после изменения Addend > 0, то возвращается положительное число, не обязательно равное Addend.
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.

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



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

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