Kim korkar Semaphore’dan
Merhabalar,
Senkronizasyon (synchronization) mekanizmalarından biri olan Semaphore’la ilgili bir örnek yapacağız.
Basit bir dille anlatmak gerekirse, Birden fazla işin (process) aynı anda çalıştığında birbirleri için risk oluşturabileceği anlarda (critical sections) , diğer işleri bekletmesini sağlatan bir mekanizma türüdür.
Bir hayali örnek ile ilerleyelim açıkçası ben alaylı olduğum için mantığını biraz geç anladım Tuğrul bey sağ olsun yardımcı oldu, Biz şimdi Semaphore’u bir berber dükkanı olarak hayal edelim.
Bir berber dükkanı açmak istedik ve parayı bulduk berber dükkanı açtık. OpenSemaphore(SEMAPHORE_ALL_ACCESS, false,PWideChar(‘yhackup’));
function OpenSemaphore(dwDesiredAccess: DWORD; bInheritHandle: BOOL; lpName: LPCWSTR): THandle; stdcall; {$EXTERNALSYM OpenSemaphore}
Semaphore berber dükkanımız küçük olduğu için şimdilik 5 koltuk koyabildik, ve Sabah dükkanı açtık 5 koltuğun 5’ide boş. CreateSemaphore(nil, 5, 5, PWideChar(‘yhackup’)
function CreateSemaphore(lpSemaphoreAttributes: PSecurityAttributes; lInitialCount, lMaximumCount: Longint; lpName: LPCWSTR): THandle; stdcall;
5 koltuğu olan bir berberde bir koltuğa 2 kişi oturamaz veya bir berber 2 kişiyi traş edemez , aynı ipte iki cambaz oynamaz.
Her bir berber(TThread) bir kişi alarak traşını yapar, yeni gelen saçı sakalı birbirine karışmış bireyler sırasını bekler. WaitForSingleObject(MySemaphore, INFINITE);
function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; stdcall;
Her bir berberin bir kişiyi traş etmesi 5 saniye sürer. Sleep(5000);
procedure Sleep(milliseconds: Cardinal); stdcall;
Traş olan kişi parasını öder koltuktan kalkar ReleaseSemaphore(MySemaphore, 1, nil); ve 1 kişilik yer açılır. yeni Müşteri gelir.
function ReleaseSemaphore(hSemaphore: THandle; lReleaseCount: Longint; lpPreviousCount: Pointer): BOOL; stdcall;
Kodlara geçmeden sistemin nasıl çalıştığını gösteren bir video izleyelim.
unit USemaphore; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TSemaForm = class(TForm) GroupBox1: TGroupBox; GroupBox2: TGroupBox; GroupBox3: TGroupBox; iceridekilist: TListBox; bekleyenlist: TListBox; cikanlist: TListBox; CreateButton: TButton; procedure FormCreate(Sender: TObject); procedure AddList(Text: String; Wait: Integer); procedure NewSemaphore(Text: String); procedure CreateButtonClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var SemaForm: TSemaForm; MySemaphore: THandle; a: integer = 0; implementation {$R *.dfm} procedure TSemaForm.AddList(Text: String; Wait: Integer); begin case Wait of 0: // Bekliyor listesine ekle begin TThread.Queue(nil, procedure begin bekleyenlist.Items.Add(Text); end); end; 1: // İçeride listesine ekle begin TThread.Queue(nil, procedure var i: integer; begin for I := 0 to bekleyenlist.Count - 1 do begin if bekleyenlist.Items[i] = Text then begin bekleyenlist.Items.Delete(i); iceridekilist.Items.Add(Text); Break; end; end; end); end; 2: // Bitti listesine ekle begin TThread.Queue(nil, procedure var i: integer; begin for I := 0 to iceridekilist.Count - 1 do begin if iceridekilist.Items[i] = Text then begin iceridekilist.Items.Delete(i); cikanlist.Items.Add(Text); Break; end; end; end); end; end; end; procedure TSemaForm.CreateButtonClick(Sender: TObject); begin NewSemaphore('Semaphore-' + IntToStr(a)); Inc(a); end; procedure TSemaForm.FormCreate(Sender: TObject); begin MySemaphore := OpenSemaphore(SEMAPHORE_ALL_ACCESS, false,PWideChar('yhackup')); if MySemaphore = 0 then begin // 5 kişilik yer var, 5 yer de boş MySemaphore := CreateSemaphore(nil, 5, 5, PWideChar('yhackup')); end; end; procedure TSemaForm.NewSemaphore(Text: String); var str: string; begin str := Text; TThread.CreateAnonymousThread( procedure begin // Dükkana Yeni müşteri geliyor, // Eğer 5 koltukta dolu ise MySemaphore berberinde, // kişi INFINITE kadar bekliyor. // ReleaseSemaphore ile bir kişilik yer açıltığında. AddList(str, 0); WaitForSingleObject(MySemaphore, INFINITE); // Boş koltuğa geçebiliyor. // kişi Burada Traş Olmakta AddList(str, 1); Sleep(5000); // kişi Burada Traş Olmakta // Traş burada bitiyor, Berberin çıkış kapısından müşteri çıkıyor.. ReleaseSemaphore(MySemaphore, 1, nil); AddList(str, 2); end).Start; end; end.
Kalın Sağlıcakla…