Работа с мютекси в OOP стил (Delphi, TMutex)

Mutex механизмът е проектиран да гарантира, че не повече от една нишка може да работи едновременно с ресурс.

Има два начина за работа с мютекси в Delphi.

  1. Използването на "обичайно" ниско ниво (WinAPI) функции (CreateMutex и др.).
    Този метод работи в почти всички версии, отдавна е овладян от програмисти и не се нуждае от допълнително описание (има повече от достатъчно материали по тази тема в Delphi в Интернет). Нека го наречем „класическия начин“;
  2. Използване на класTMutex.
    Този клас се появи за първи път във версията XE. Той осигурява опростен интерфейс за работа с мютекси и почти напълно елиминира необходимостта от използване на функции на ниско ниво при работа с тях.

Помислете за втория начин.

Класът TMutex е описан в модула System.SyncObjs. Неговият конструктор има три претоварвания.

Най-предпочитаното претоварване за създаване на мютекс е:

  • Първият параметър (TSecurityAttributes) е указател за записване на атрибути на защитата (в най-простия случай е разрешено нула).
  • Вторият параметър (Boolean) определя дали нишката, създала мутекса, ще стане негов собственик;
  • Третият параметър (String) е уникалното име на мютекса.
  • Четвъртият параметър (Boolean) е способността на mutex да работи с COM компоненти на STA (апартамент с една нишка). Този параметър е по избор и по подразбиране е false.

Второто претоварване отваря вече съществуващ мютекс с уникално име (приетите параметри са същите като предишния).

Третото претоварване създава нов мютекс, но отнема само един параметър, възможността за работа със STA COM.

В процеса на работа с TMutex се използват главно три от методите му:

  • Придобиване - улавяне на мютекс;
  • Освобождаване - освобождаване на мютекса;
  • WaitFor - изчакване за достъп до мютекса за известно време (таймаут). Методът е наследен от предшественика - клас THandleObject.

Времето за изчакване се определя от единствения параметър на този метод. Ако се изисква да изчакате неопределен период от време, стойността INFINITE се предава.

За разлика от функцията WaitForSingleObject, използвана в метода "класически", този метод връща стойността на изброяването на TWaitResult. Следователно не можете директно да го сравните с WAIT_TIMEOUT (в противен случай това не е необходимо).

В предишната статия за мютексите вече беше отбелязано, че има два основни подхода за тяхното използване.

  • В зависимост от състоянието на мютекса незабавно се предприемат съответните действия. Нишката, осъществяваща достъп до мутекса, не спира работата си;
  • Нишката, която е осъществила достъп до мутекса, изчаква да бъде освободена и едва след това продължава да работи.

Нека покажем изпълнението на двата подхода с помощта на TMutex.

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