-【内核对象线程同步】成功等待的副作用

来源:互联网 发布:数组是物理结构么 编辑:程序博客网 时间:2024/05/15 16:03
 

对于有些内核对象来说,成功地调用WaitForSingleObject和WaitForMultipleObjects,实际上会改变对象的状态。

成功地调用是指函数发现对象已经得到通知并且返回一个相对于WAIT_OBJECT_0的值。如果函数返回WAIT_TIMEOUT或WAIT_FAILED,那么调用就没有成功。如果函数调用没有成功,对象的状态就不可能改变。

当一个对象的状态改变时,称之为成功等待的副作用

例如,有一个线程正在等待自动清除事件对象。当事件对象变为已通知状态时,函数就会发现这个情况,并将WAIT_OBJECT_0返回给调用线程。但是就在函数返回之前,该事件将被置为未通知状态,这就是成功等待的副作用。

对象拥有不同的副作用,而有些对象则根本没有任何副作用。进程和线程内核对象就根本没有任何副作用,也就是说,在这些对象之一上进行等待决不会改变对象的状态。

  究竟是什么原因使得WaitForMultipleObjects函数如此有用呢,因为它能够以原子操作方式来执行它的所有操作。当一个线程调用WaitForMultipleObjects函数时,该函数能够测试所有对象的通知状态,并且能够将所有必要的副作用作为一项操作来执行。

 

等待事件的例子

两个线程以完全相同的方式来调用WaitForMultipleObjects:

HANDLE h[2];

h[0] = hAutoResetEvent1;  // Initially nonsignaled

h[1] = hAutoResetEvent2;  // Initially nonsignaled

WaitForMultipleObjects(2, h, TRUE, INFINITE);

当WaitForMultipleObjects函数被调用时,两个事件都处于未通知状态,这就迫使两个线程都进入等待状态。然后hAutoResetEvent1对象变为已通知状态。两个线程都发现,该事件已经变为已通知状态,但是它们都无法被唤醒,因为hAutoResetEvent2仍然处于未通知状态。由于两个线程都没有等待成功,因此没有对hAutoResetEvent1对象产生任何副作用。

接着,hAutoResetEvent2变为已通知状态。这时,两个线程中的一个发现,两个对象都变为已通知状态。等待取得了成功,两个事件对象均被置为未通知状态,该线程变为可调度的线程。但是另一个线程的情况如何呢?它将继续等待,直到它发现两个事件对象都处于已通知状态。尽管它原先发现hAutoResetEvent1处于已通知状态,但是现在它将该对象视为未通知状态。

原创粉丝点击