LoginSignup
6
1

More than 1 year has passed since last update.

<7> セマフォ (同期オブジェクト) (Delphi コンカレントプログラミング)

Last updated at Posted at 2021-12-13

7. セマフォ (同期オブジェクト)

セマフォ (Semaphore) は同期オブジェクトの一つです 1。所定の数のスレッドのアクセスを許可します。

スレッドカウンタの最大数が 1 のセマフォをバイナリセマフォと呼び、ミューテックスと同等となります。

7.1. TSemaphore

TSemaphore クラス 2 を使うと、指定された数のスレッドからしかアクセスできない機構を作る事ができます。TSemaphoreSystem.SyncObjs で定義されています。

最初の書式のコンストラクタではカウンタの初期値が 1 の無名セマフォを作成します。無名セマフォはローカルセマフォで、Critical Section と同等の動作になります。よって、このコンストラクタを使うとミューテックスと同等の動作になります。セマフォの作成に失敗すると EOSError が発生します。

二番目の書式のコンストラクタでは、名前付きのセマフォを作成します (名前が空でない場合はシステムセマフォ)。セマフォの作成に失敗すると EOSError が発生します。

三番目の書式のコンストラクタでは名前付きのセマフォを開きます。セマフォが開けなかった場合には EOSError が発生します。Windows 環境でない場合には名前付きのセマフォを作成します。

constructor Create(UseCOMWait: Boolean = False);
constructor Create(SemaphoreAttributes: PSecurityAttributes; AInitialCount, AMaximumCount: Integer; const Name: string; UseCOMWait: Boolean = False);
constructor Create(DesiredAccess: Cardinal; InheritHandle: Boolean; const Name: string; UseCOMWait: Boolean = False);

最初期のこのクラスは Windows API をラップしたものでした。

Delphi Windows API
TSemaphore.Create() コンストラクタ CreateSemaphoreW()
TSemaphore.Create() コンストラクタ OpenSemaphoreW()
TSemaphore.Release() メソッド ReleaseSemaphore()

使い方は TMutex とほぼ同じです。

See also:

7.1.1. TSemaphore を使った起動数の制御

ちょっとマルチスレッドからは離れますが、プロセス間同期オブジェクト (システムセマフォ) としての使い方です。

TMutex のような要領で、指定された数しか開けないアプリケーションを作る方法です。

program Project1;

uses
  Vcl.Forms,
  System.SysUtils,
  System.SyncObjs,
  WinAPI.Windows,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

const
  SEMAPHORE_NAME = 'Global\MyApp';

begin
  ReportMemoryLeaksOnShutdown := True;
  Application.Initialize;
  var oSemaphore, cSemaphore: TSemaphore;
  try
    oSemaphore := TSemaphore.Create(SEMAPHORE_ALL_ACCESS, False, SEMAPHORE_NAME);
  except
    on E: EOSError do
      cSemaphore := TSemaphore.Create(nil, 2, 3, SEMAPHORE_NAME);
  end;
  if Assigned(oSemaphore) and (oSemaphore.WaitFor(0) <> wrSignaled) then
    begin
      Application.MessageBox('3つまでしか開けないよ!', 'エラー', MB_ICONERROR or MB_OK);
    end
  else
    begin
      Application.MainFormOnTaskbar := True;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
      if Assigned(oSemaphore) then
        oSemaphore.Release;
    end;
  FreeAndNil(cSemaphore);
  FreeAndNil(oSemaphore);
end.

素の Windows API を使った方が簡単な気もします。

7.2. TLightweightSemaphore

TLightweightSemaphore クラス 3 は軽量なセマフォです。System.SyncObjs で定義されています。但し、ローカルセマフォとしてしか使えません。

.NET の SemaphoreSlim クラスに相当します。

See also:

参考

索引

[ ← 6. ミューテックス (同期オブジェクト) ] [ ↑ 目次へ ] [ → <8> イベント (同期オブジェクト) ]


  1. 語源となったのは腕木式信号機です。僕がこの用語を初めて知ったのは『SX‐WINDOWプログラミング』だったと思います。 

  2. TSemaphore は Delphi 2009 以降で利用可能です。 

  3. TLightweightSemaphore は Delphi XE 以降で利用可能です。え?TLightweightMutex が存在しない理由ですか? 

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1