在论坛上看到一网友问一关于互斥量问题,我稍微做了些修改,代码如下:
int main()
{
HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
WaitForSingleObject(hMutex, INFINITE);
WaitForSingleObject(hMutex, INFINITE);
printf("test mutex\n");
return 0;
}
问WaitForSingleObject 为什么没有阻塞?
很显然CreateMutex第二个参数传的是FALSE, 互斥量内核对象的线程ID和递归计数都为0,即创建后的状态是已触发的。线程在调用WaitForSingleObject的时候,相应的内核对象如果已经处于触发状态,线程是不会进入等待状态的,只会把内核对象的线程ID设为调用线程ID,把递归计数设为1。第二次调用WaitForSingleObject 同样不会阻塞,这是由于互斥量内核对象不同于普通内核对象的地方:如果当前线程已经拥有互斥量对象,再次调用WaitForSingleObject, 系统会检查调用线程ID与内核对象记录的线程ID是否一致,如果一致那么调用线程会仍然处于可调度状态,即使互斥量处于未触发状态。
到此,我在想如果初始创建的互斥量处于未触发状态,也就是第二个参数传入TRUE,线程是否会阻塞于第一个WaitForSingleObject ? 我觉得会,因为在等待内核对象触发啊,可试了一下发现并没有阻塞。原来CreateMutex在传入TRUE 的情况下, 对象的线程ID将被设为调用线程的线程ID,递归计数被设为1。之后的解释就如上面所述了。
总结:
(1)互斥量线程ID是判断互斥量对象状态的依据,0 已触发,非0未触发。
(2)同一线程多次WaitForSingleObject同一互斥量对象,系统依据互斥量对象线程ID决定是否挂起线程。