CreateSemaphore セマフォオブジェクトの作成

Cの宣言:

HANDLE CreateSemaphore(
	LPSECURITY_ATTRIBUTES Security,
	LONG InitialCount,
	LONG MaxCount,
	LPCTSTR SemaphoreName);

説明:

セマフォオブジェクトを作成する。SemaphoreNameで指定したセマフォオブジェクトが既に存在する場合、このセマフォオブジェクトをオープンし、そのハンドルを返す。

関数の実行が成功すると、セマフォオブジェクトのハンドルが返される。新規セマフォオブジェクトが作成された場合は、GetLastError()の戻り値は0となり、既存のセマフォオブジェクトがオープンされた場合は、GetLastError()の戻り値はERROR_ALREADY_EXISTINGとなる。

名前のないセマフォオブジェクトを作成することも可能である。この場合、そのセマフォオブジェクトへの参照は、ハンドルによってのみ可能となる。名前の無いセマフォオブジェクトは複数作成可能であり、ハンドルによって識別される。

取得したハンドルは、CloseHandleによって解放する。オープンされているハンドルが全てクローズされると、システムは自動的にセマフォオブジェクトを削除する。

セマフォオブジェクトは、内部にカウンタとカウンタの最大数を持つオブジェクトである。カウンタの初期値はInitialCountで、カウンタの最大数はMaxCountで指定される。待機関数を実行するとカウンタが1減少し、ReleaseSemaphore関数を実行するとカウンタが増加する。ただし、カウンタは常に0からMaxCountの間の値を取る。

セマフォオブジェクトの内部カウンタが0のとき、待機関数は再び内部カウンタが1以上になるまで待機する。この機構により、リソースの同時アクセス数の制限などの排他制御が可能となる。

引数の意味は、以下の通り。

Security (IN) セマフォオブジェクトのセキュリティ属性。
InitialCount (IN) セマフォオブジェクトの内部カウンタの初期値。
MaxCount (IN) セマフォオブジェクトの内部カウンタの最大値。
SemaphoreName (IN) セマフォオブジェクトの名前。NULLを指定した場合、名前の無いセマフォオブジェクトが作成される。

名前付きセマフォの例(C言語):

#define SEMAPHORE_NAME "Test Semaphore Object"
 
/* アプリケーションを1度に3つまでしか実行できないようにする */
int main()
{
	HANDLE hSemaphore;
	DWORD result;

	/* セマフォオブジェクトの作成/取得 */
	hSemaphore = CreateSemaphore(NULL, 3, 3, SEMAPHORE_NAME);
	result = WaitForSingleObject(hSemaphore, 0);

	/* すでに3つ開いているかどうか判定 */
	if(result != WAIT_OBJECT_0) {
		printf("既に3つ開いている\n");
	} else {
		/* 処理 */
		printf("処理開始\n");
		Sleep(10000);
		printf("処理終了\n");

		/* 解放 */
		ReleaseSemaphore(hSemaphore, 1, NULL);
	}

	CloseHandle(hSemaphore);
	return(0);
}

名前無しセマフォの例(C言語):

同時に3つまでしか起動できないスレッドの排他制御を、名前の無いセマフォオブジェクトを用いて実装する。
/* セマフォオブジェクトのハンドル */
HANDLE g_hSemaphore;
 
/* 1度に3つまでしか実行できないスレッド関数	*/
DWORD WINAPI DoThread(DWORD ThreadCount)
{
	/* 待機 */
	WaitForSingleObject(g_hSemaphore, INFINITE);

	/* 処理 */
	printf("スレッド%d: 処理開始\n", ThreadCount);
	Sleep(1000);
	printf("スレッド%d: 処理終了\n", ThreadCount);

	/* 後処理 */
	ReleaseSemaphore(g_hSemaphore, 1, NULL);
	return(0);
        
}

/* メイン関数 */
int main(int argc, char **argv)
{
	HANDLE hThread[5];
	int i;
	
	/* セマフォオブジェクトの作成 */
	g_hSemaphore = CreateSemaphore(NULL, 3, 3, NULL);

	/* スレッドを5つ作成 */
	for(i=0; i<5; i++) {
		hThread[i] = CreateThread(
			NULL, 0, (LPTHREAD_START_ROUTINE)DoThread,
			(LPVOID)i, 0, NULL);
		Sleep(100);
	}

	/* スレッドの終了まで待機 */
	WaitForMultipleObjects(5, hThread, TRUE, INFINITE);

	/* 後処理 */
	CloseHandle(g_hSemaphore);
	
	for(i=0; i<5; i++) CloseHandle(hThread[i]);
	return(0);
}
(original text:1998/12/25 更新)

本ドキュメントの内容は保証しません。本ドキュメントによって生じた結果について、一切の責任を負いません。