Mutex(互斥量)

来源:互联网 发布:win10下装linux双系统 编辑:程序博客网 时间:2024/06/05 23:47

一、What is Mutex(互斥量)

互斥量是用于线程同步的内核对象,用来确保一个线程独占对一个资源的访问.

互斥量包含:

使用计数
线程ID
递归计数
其中:
线程ID—— 标识当前占用这个互斥量的是系统中的哪个线程
递归计数——这个线程占用该互斥量的次数
线程ID为0表示没有线程占用该互斥量,即互斥量处于触发状态.

二、Rules

1.如果线程ID为0(无效线程ID),那么该互斥量不为任何线程所占用,它处于触发状态.

2.如果线程ID为非0值,那么有一个线程已经占用了该互斥量,它处于未触发状态.此时递归计数>=1.

3.特殊规则:
调用wait函数等待Mutex时,系统会检查想要获得互斥量的线程的线程ID与互斥量对象内部记录的线程ID是否相同.
如果线程ID一致,那么系统会让线程保持可调度状态,即使该互斥量尚未触发.每次线程成功地等待了一个互斥量,
互斥量对象的递归计数都会递增1.
使递归计数大于1的唯一途径是利用这个例外,让线程多次等待同一个互斥量.

4.当目前占有访问权的线程不再需要访问资源的时候,它必须调用ReleaseMutex函数来释放互斥量.
这个函数会将Mutex的递归计数减1.如果线程成功地等待了互斥量对象不止一次,那么线程必须调用ReleaseMutex相同的次数
才能使对象的递归计数变为0.
当递归计数变成0时,函数还会将线程ID设为0,这样就触发了Mutex.

三、API

1.

HANDLE WINAPI CreateMutex(     LPSECURITY_ATTRIBUTES lpMutexAttributes,     BOOL bInitialOwner,     LPCTSTR lpName);

bInitialOwner —— 控制互斥量的初始状态
FALSE:互斥量的线程ID和递归计数都将被设为0,即Mutex处于触发状态,不为任何线程所占用.
TRUE :互斥量的线程ID被设为调用线程的线程ID,递归计数被设为1,Mutex处于未触发状态.

2.

BOOL WINAPI ReleaseMutex(HANDLE hMutex);

当目前占有访问权的线程不再需要访问资源的时候,它必须调用ReleaseMutex函数来释放互斥量.
这个函数会将Mutex的递归计数减1.如果线程成功地等待了互斥量对象不止一次,那么线程必须调用ReleaseMutex相同的次数
才能使对象的递归计数变为0.

当递归计数变成0时,函数还会将线程ID设为0,这样就触发了Mutex.
The ReleaseMutex function fails if the calling thread does not own the mutex object.

Note:
If a thread terminates without releasing its ownership of a mutex object, the mutex object is considered to be abandoned. A waiting thread can acquire ownership of an abandoned mutex object, but the wait function will return WAIT_ABANDONED to indicate that the mutex object is abandoned. An abandoned mutex object indicates that an error has occurred and that any shared resource being protected by the mutex object is in an undefined state. If the thread proceeds as though the mutex object had not been abandoned, it is no longer considered abandoned after the thread releases its ownership. This restores normal behavior if a handle to the mutex object is subsequently specified in a wait function.

四、Code

DWORD dw = WaitForSingleObject(g_hMutex, 1000);switch (dw){case WAIT_FAILED:     break;case WAIT_TIMEOUT:     break;case WAIT_ABANDONED:     break;case WAIT_OBJECT_0:     break;default:     break;}
0 0