核心编程第9章讲到:it's important to note that WaitForMultipleObjects works atomically. When it checks the state of the kernel objects, no other thread can alter any object's state behind its back. This prevents deadlock situations. Imagine what would happen if one thread saw that hAuto-ResetEvent1 was signaled and reset the event to nonsignaled, and then the other thread saw that hAutoResetEvent2 was signaled and reset this event to nonsignaled. Both threads would be frozen: one thread would wait for an object that another thread had gotten, and vice versa. WaitFor-MultipleObjects ensures that this never happens.
说WaitForMultipleObjects是以原子方式工作的,当它检查内核对象的状态时,没有其他线程能在背后改变对象的状态。
这和MSDN里的说法似乎是矛盾的:
When bWaitAll is TRUE, the function's wait operation is completed only when the states of all objects have been set to signaled. The function does not modify the states of the specified objects until the states of all objects have been set to signaled. For example, a mutex can be signaled, but the thread does not get ownership until the states of the other objects are also set to signaled. In the meantime, some other thread may get ownership of the mutex, thereby setting its state to nonsignaled.
个人觉得Jeffrey可能没表达清楚他的意思,MSDN在这里说的没问题。等待函数工作的时候,不可能不允许别的线程SetEvent吧?
不知各位大神有何高见?线程同步

解决方案 »

  1.   

    如果别的线程不能更改,wait线程又挂起等待,那不over了。
      

  2.   

    楼主这是断章取义,完全没理解Richter和MSDN的意思。
    Richter原文件附后的代码如下:HANDLE h[2];
    h[0] = hAutoResetEvent1;
    h[1] = hAutoResetEvent2;
    WaitForMultipleObjects(2, h, TRUE, INFINITE);Richter说WaitForMultipleObjects是原子操作,是指WaitForMultipleObjects的检测过程中,如果检测到一个对象被触发了,但不是全部对象被触发,那么不会引发被触发对象的副作用,也就是不会把这个已触发的对象再自动设置为未触发。只有当WaitForMultipleObjects检测到所有对象都已被触发的情况下,才把所有对象设置为未触发对象。
    比如,如果只检测到hAutoResetEvent1被触发,这仅仅是检测到而已,不会更改hAutoResetEvent1的状态。这与MSDN的说法“When bWaitAll is TRUE, the function's wait operation is completed only when the states of all objects have been set to signaled. The function does not modify the states of the specified objects until the states of all objects have been set to signaled”是一致的。
    Richter举了个例子,假如WaitForMultipleObjects不是原子操作,有两个线程都以上面相同代码的方式来调用WaitForMultipleObjects,开始时hAutoResetEvent1和hAutoResetEvent2都是未触发状态,两个线程都继续等待。接下来hAutoResetEvent1被触发,线程1首先检测到了,因为我们假设的WaitForMultipleObjects不是原子操作,那么线程1的WaitForMultipleObjects将把hAutoResetEvent1设置为未触发状态;然后CPU切换到线程2,这个时间hAutoResetEvent2被触发,线程2检测到了,线程2的WaitForMultipleObjects将把hAutoResetEvent2设置为未触发状态,然后线程2继续等待hAutoResetEvent1被触发。与此同时,线程1继续等待hAutoResetEvent2的触发。毫无疑问,这造成了DeadLock。
    而MSDN“In the meantime, some other thread may get ownership of the mutex, thereby setting its state to nonsignaled.”这句话的意思是,在线程1和线程2等待的同时,另一个线程3是有机会获取对象的所有权,并更改对象的状态的。
      

  3.   

    致3楼BeanJoy:
    其实我也是这么理解的,但我觉得Jeffrey这段话确实讲得不太清楚,不够严谨,容易产生歧义。
      

  4.   

    请教3楼,以你讲述的这个情况为基础,再启动一个单独的工作线程去 
    WaitForSingleObject(hAutoResetEvent1, INFINITE); // 或者是 hAutoResetEvent2
    会产生什么结果?
      

  5.   

    其他线程用WaitForSingleObject可能先等到其中一个自动事件,并且将其置为未触发状态。或者其他线程可能调用ResetEvent将其中一个事件置为未触发状态。
    WaitForMultipleObjects显然对这两种情况无能为力。
      

  6.   

    第一个是针对多个objects触发的检测,后一个说的是某一个object的检测