Semaphore
A semaphore is a synchronization object that manages access to a finite number of resources. Windows provides both unnamed and named semaphores for interprocess synchronization.
Overview
Syntax
Remarks
Examples
Key Points
- Count represents the number of available resources.
- When a thread calls
WaitForSingleObject
, the count is decremented. - If the count is zero, the thread blocks until a release occurs.
- Use
ReleaseSemaphore
to increase the count and unblock waiting threads.
When to Use
Semaphores are ideal for limiting concurrency, such as controlling the number of threads that can access a pool of database connections.
Function Syntax
#include <windows.h>
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCSTR lpName
);
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
Remarks
Semaphores can be named, allowing multiple processes to share the same synchronization object. The name is case‑insensitive and must be unique within the system.
Parameter | Description |
---|---|
lpSemaphoreAttributes | Optional security descriptor. |
lInitialCount | Initial number of resources. |
lMaximumCount | Maximum count allowed. |
lpName | Optional object name. |
Example: Controlling Access to a Resource Pool
#include <windows.h>
#include <stdio.h>
#define POOL_SIZE 3
HANDLE g_hSem;
DWORD WINAPI Worker(LPVOID lpParam) {
DWORD id = GetCurrentThreadId();
printf("Thread %lu waiting for resource...\\n", id);
WaitForSingleObject(g_hSem, INFINITE);
printf("Thread %lu acquired resource.\\n", id);
Sleep(2000); // simulate work
printf("Thread %lu releasing resource.\\n", id);
ReleaseSemaphore(g_hSem, 1, NULL);
return 0;
}
int main(void) {
g_hSem = CreateSemaphore(NULL, POOL_SIZE, POOL_SIZE, NULL);
if (!g_hSem) {
printf("CreateSemaphore failed (%lu)\\n", GetLastError());
return 1;
}
HANDLE hThreads[5];
for (int i = 0; i < 5; ++i) {
hThreads[i] = CreateThread(NULL, 0, Worker, NULL, 0, NULL);
}
WaitForMultipleObjects(5, hThreads, TRUE, INFINITE);
CloseHandle(g_hSem);
return 0;
}