windows 使用 Semaphore 进行同步

使用Semaphore进行线程同步

#include <windows.h>
#include <stdio.h>

#define MAX_SEM_COUNT 2
#define THREADCOUNT 3

HANDLE ghSemaphore;

DWORD WINAPI ThreadProc(LPVOID);

int main(void)
{
	HANDLE aThread[THREADCOUNT];
	DWORD ThreadID;
	int i;

	// Create a semaphore with initial and max counts of MAX_SEM_COUNT

	ghSemaphore = CreateSemaphore(
		NULL,           // default security attributes
		MAX_SEM_COUNT,  // initial count   //初始化资源为2
		MAX_SEM_COUNT,  // maximum count   //初始化资源最大数为2
		NULL);          // unnamed semaphore

	if (ghSemaphore == NULL)
	{
		printf("CreateSemaphore error: %d\n", GetLastError());
		return 1;
	}

	// Create worker threads

	for (i = 0; i < THREADCOUNT; i++)
	{
		aThread[i] = CreateThread(
			NULL,       // default security attributes
			0,          // default stack size
			(LPTHREAD_START_ROUTINE)ThreadProc,
			NULL,       // no thread function arguments
			0,          // default creation flags
			&ThreadID); // receive thread identifier

		if (aThread[i] == NULL)
		{
			printf("CreateThread error: %d\n", GetLastError());
			return 1;
		}
	}

	// Wait for all threads to terminate

	WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

	// Close thread and semaphore handles

	for (i = 0; i < THREADCOUNT; i++)
		CloseHandle(aThread[i]);

	CloseHandle(ghSemaphore);

	return 0;
}

DWORD WINAPI ThreadProc(LPVOID lpParam)
{

	// lpParam not used in this example
	UNREFERENCED_PARAMETER(lpParam);

	DWORD dwWaitResult;
	BOOL bContinue = TRUE;


	dwWaitResult = WaitForSingleObject(   //当线程使用WaitForSingleObject从ghSemaphore中获取到信号时,资源计数减少1,当ghSemaphore没有资源时,并且参数为INFINITE WaitForSingleObject会卡住
		ghSemaphore,   // handle to semaphore
		INFINITE);           // zero-second time-out interval


	printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
	bContinue = FALSE;

	// Simulate thread spending time on task
	Sleep(5000);

	// Release the semaphore when task is finished

	if (!ReleaseSemaphore( // 该API使ghSemaphore的内部资源计数加1
		ghSemaphore,  // handle to semaphore
		1,            // increase count by one
		NULL))       // not interested in previous count
	{
		printf("ReleaseSemaphore error: %d\n", GetLastError());
	}


	// The semaphore was nonsignaled, so a time-out occurred.
	return TRUE;
}

上面的代码我启动了三个进程,为信号分配了两个资源,那么在程序开始时,有两个线程先通过WaitForSingleObject获取到信号,此时信号的资源计数减到0,执行printf,然后等5s,有一个线程调用了ReleaseSemaphore,使资源计数加1,最后一个线程也执行printf,等待5s,最后所有线程结束,程序退出

使用Semaphore进行进程同步

server.exe

#include <Windows.h>
#include <stdio.h>
#include <locale>

int main() {
	setlocale(LC_ALL, "zh_CN.UTF-8");
	TCHAR szCommandLine[] = TEXT("client.exe");//或者WCHAR

	STARTUPINFO si;

	PROCESS_INFORMATION pi;

	ZeroMemory(&si, sizeof(si));

	si.cb = sizeof(si);

	ZeroMemory(&pi, sizeof(pi));



	si.dwFlags = STARTF_USESHOWWINDOW;

	si.wShowWindow = TRUE;


	BOOL bRet = ::CreateProcess(NULL,szCommandLine,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi);



	if (bRet)

	{
		LONG pre;
		wchar_t wszPid[MAX_PATH] = { 0, };
		wsprintf(wszPid, L"%d", pi.dwProcessId);
		HANDLE semaphore = CreateSemaphore(0, 0, 1, wszPid);
		wprintf(TEXT("按下Enter键发送信号"));
		getchar();
		ReleaseSemaphore(semaphore, 1, &pre);
		wprintf(TEXT("信号已发送"));
		WaitForSingleObject(pi.hProcess, INFINITE);

		// 既然我们不使用两个句柄,最好是立刻将它们关闭

		::CloseHandle(pi.hThread);

		::CloseHandle(pi.hProcess);

		CloseHandle(semaphore);

	}

	return 0;
}

client.exe

#include <Windows.h>
#include <stdio.h>
#include <locale.h>
int main() {
	setlocale(LC_ALL, "zh_CN.UTF-8");
	wchar_t wszPid[MAX_PATH] = {0,};
	DWORD processId = GetCurrentProcessId();

	wsprintf(wszPid, TEXT("%d"), processId);
	HANDLE semaphore =  OpenSemaphore(EVENT_ALL_ACCESS, FALSE, wszPid);
	wprintf(TEXT("等待信号发送\n"));
	WaitForSingleObject(semaphore, INFINITE);
	wprintf(TEXT("获取到信号"));
	getchar();
	return 0;
}

server.exe创建子进程client.exe,获取子进程的pid,创建信号,资源计数设置0,最大资源计数设置为1,然后getchar()卡住界面,子进程client.exe获取自己的pid,打开信号,使用WaitForSingleObject等待信号。server.exe按任意键继续,使用ReleaseSemaphore增加信号资源计数,子进程client.exe,接收到信号,打印消息,最后程序退出

posted @ 2023-03-10 15:33  乘舟凉  阅读(28)  评论(0编辑  收藏  举报