Synchronizace za pomocí System.TMonitor

vložil Radek Červinka 2. června 2010 23:06

V Delphi 2009 byla přidána pěkná možnost synchronizace přístupu k objektům. Do RTL, konkrétně system.pas, byl pro synchronizaci přidán záznam TMonitor (podobně je to řešeno v .NET).

Už několikrát jsem upozorňoval na opravdu nádherné možnosti získané díky rozšíření funkcionality record (alias záznamu). V starých Delphi byl záznam prostě jen blok strukturovaných dat, kdežto nyní nad ním můžete definovat metody, typy, class metody, případně class proměnné, viz. wiki Embarcadera. Níže schválně uvádím deklaraci TMonitor, samozřejmě nás zajímá jen sekce public, zbytek je jen jako příklad.

  PPMonitor = ^PMonitor;
  PMonitor = ^TMonitor;

  TMonitor = record
  strict private
    type
      PWaitingThread = ^TWaitingThread;
      TWaitingThread = record
        Next: PWaitingThread;
        Thread: Cardinal;
        WaitEvent: Pointer;
      end;
    var
      FLockCount: Integer;
      FRecursionCount: Integer;
      FOwningThread: Cardinal;
      FLockEvent: Pointer;
      FSpinCount: Integer;
      FWaitQueue: PWaitingThread;
    procedure QueueWaiter(var WaitingThread: TWaitingThread);
..
  public
    class procedure SetSpinCount(AObject: TObject; ASpinCount: Integer); static;
    class procedure Enter(AObject: TObject); overload; static; inline;
    class function Enter(AObject: TObject; Timeout: Cardinal): Boolean; overload; static;
    class procedure Exit(AObject: TObject); overload; static;
    class function TryEnter(AObject: TObject): Boolean; overload; static;
    class function Wait(AObject: TObject; Timeout: Cardinal): Boolean; overload; static;
    class procedure Pulse(AObject: TObject); overload; static;
    class procedure PulseAll(AObject: TObject); overload; static;
  end;

Pojmenování TMonitor není moc štastné, jelikož v jednotce Forms.pas již jeden TMonitor existuje, takže pozor na záměnu.

Kromě samostatného záznamu je v RTL několik procedur, které lze jednoduše použít.

function MonitorEnter(AObject: TObject; Timeout: Cardinal = INFINITE): Boolean; inline;
function MonitorTryEnter(AObject: TObject): Boolean; inline;
procedure MonitorExit(AObject: TObject); inline;
function MonitorWait(AObject: TObject; Timeout: Cardinal): Boolean; inline;
procedure MonitorPulse(AObject: TObject); inline;
procedure MonitorPulseAll(AObject: TObject); inline;

procedure MemoryBarrier;
procedure YieldProcessor; 

Jen pro úplnost: veškeré synchronizace jsou nahraditelné za vlastní obsluhu. Metody z TMonitor interně volají procedury definované přes System.MonitorSupport, takže pokud se vám nelíbí standardní obsluha (definovaná v SysUtils), nic Vám nebrání do System.MonitorSupport přiřadit vlastní implementace.

Použití TMonitor je přímočaré: kdekoliv potřebujeme přistupovat ke sdíleným datům z více vláken napíšeme např. pro přístup ke sdílenému TList

  System.TMonitor.Enter(list);
  try
    list.Add(….);
    …
  finally
    System.TMonitor.Exit(list); //vždy přes finally aby nedošlo při chybě k zablokování v tomto případě list
  end;

ekvivalentem je volání přes uvedené procedury

  MonitorEnter(list);
  try
    list.Add(….);
    …
  finally
    MonitorExit(list); //vždy přes finally, aby nedošlo při chybě k zablokování v tomto případě na objektu list
  end;

Kromě Enter a Exit, lze ještě využít Enter s dobou čekání (tj. vlákno bude čekat jen určitý čas na přístup k objektu jinak se volání ukončí a vrátí se False. Jinak ještě je možnost TryEnter, kdy se jen pokusíme o přístup bez čekání, Wait kdy se daný objekt zamkne po určitou dobu nebo Pulse a PulseAll co podle nápovědy jejich volání upozorní čekající vlákno(a), že první (jeden z čekajících) může zamknout objekt hned po opuštění drženým vláknem. Přiznám se, že mne moc nenapadá na co by to mohlo být dobré (třeba to někdo v komentářích ujasní). Ale tipuji, že většinou bude stačit kombinace Enter - Exit jak bylo naznačeno v příkladu.

Tagy: , , ,

Delphi

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců