信号量同步能够很好的解决线程执行顺序。
HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName );
第一个参数第四个参数和前面事件内核对象的一样。
第二个参数:表示当前可用资源数量。为0的时候,说明没有资源可用,线程进入阻塞状态。
第三个参数:表示可用资源的最大数。
当一个线程通过WaitForSingleObject函数得到资源之后,系统会自动将可用资源减一。
这是原子操作。可以放心使用!
当线程用完资源的时候可以使用
BOOL ReleaseSemaphore(HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount );
这个函数将资源释放。
第一个参数:等待的内核句柄对象
第二个参数:释放资源的个数,一般为1.
第三个参数:返回当前可用资源的数量。
实例:
#include <iostream>
#include <windows.h>
using namespace std;
#define MAX_THREAD 10
HANDLE handle_single;
char s = 'A' ;
char sz[MAX_THREAD + 10 ];
CRITICAL_SECTION cs;
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
WaitForSingleObject( handle_single , INFINITE );
EnterCriticalSection(&cs);
strcat( sz , &s );
s++;
LeaveCriticalSection(&cs);
ReleaseSemaphore( handle_single , 1 , NULL );
return 0;
}
int main(int argc, char* argv[])
{
HANDLE hand[MAX_THREAD];
handle_single = CreateSemaphore( NULL , 0 , 1 , NULL );
sz[0] = 'S';
InitializeCriticalSection(&cs);
for (int i = 0 ; i < MAX_THREAD ; ++i )
{
hand[i] = CreateThread( NULL , 0 , ThreadProc , NULL , 0 , NULL );
}
ReleaseSemaphore( handle_single , 1 , NULL );
WaitForMultipleObjects( MAX_THREAD , hand , true , INFINITE );
cout<<sz<<endl;
for (i = 0 ; i < MAX_THREAD ; ++i )
{
CloseHandle( hand[i] );
}
CloseHandle(handle_single);
return 0;
}
显示结果:
由得到的结果可以知道,系统会记录申请资源的线程,然后逐一分配资源,应该是微软最常用的FIFO策略。
微软提供给了这么多同步使用的方法 ,他们基本上可以涵盖所有的同步事件只不过有一些书本举例不恰当,导致我们不容易理解!