我们利用互斥对象来实现线程同步。
互斥对象(mutex)属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。
互斥对象包含一个使用数量,一个线程ID和一个计数器。
ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。
创建互斥对象:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD
BOOL bInitialOwner, // initial owner
LPCTSTR lpName // object name
);
通过以下ReleaseMutex函数来实现对互斥对象的释放。
BOOL ReleaseMutex(
HANDLE hMutex // handle to mutex
);
线程必须主动申请共享对象的使用权才有可能获得该所有权,可以通过调用DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // time-out interval
);
来实现。
对于互斥对象来说,它是唯一与线程相关的内核对象。谁拥有,谁释放。
while(TRUE)
{
WaitForSingleObject(hMutex,INFINITE);
if(ticket>0)
{
cout<<"ticket 2:"<<ticket--<<endl;
}
else
break;
ReleaseMutex(hMutex); //不管是主线程还是兄弟线程,谁拥有,谁释放。
}
当调用WaitForSingleObject函数请求互斥对象时,操作系统需要判断当前请求互斥对象的线程的ID是否与互斥对象当前拥有者的线程ID相等,如果相等,即使该互斥对象处于未通知状态,调用线程仍然能够获得其所有权,然后WaitForSingleObject函数返回。对于同一个线程多次拥有的互斥对象来说,该互斥对象内部的计数器记录了该线程拥有的次数。操作系统一旦发现该线程已经终止,它就会自动将该线程所拥有的互斥对象的线程ID设为0,并将其计数器归0。
参考
[1] 孙鑫 《深入VC++》