临界区并不是解决这个问题的方法。临界区只不过是一个互斥设备。其目的是确保在给定时间只有一个线程可以执行特定的代码片段。它并非旨在用于测序,也不是特别适合该任务。问题是你不能wait在关键部分上而不获取它。
考虑这样一种情况,线程 B 必须等待线程 A 完成才能继续其工作。如果您使用关键部分(将其称为cs1
),那么你必须确保线程 A 在线程 B 尝试获取它之前获取它。这意味着您必须 100% 确定线程 A 开始执行并获取临界区,然后线程 B 才能执行潜在地获取临界区。
事件对象 http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655%28v=vs.85%29.aspx另一方面,允许您等待事件或在事件已经发生时继续。因此线程 B 可以在线程 A 启动之前等待该事件。它将等待,直到线程 A(或某人)设置事件。您描述的问题(线程 B 需要等待某些事件发生)是exactly事件对象旨在解决的问题类型。
假设有 3 个线程并行处理一段时间,但在某些时候需要等待其他事件发生,您需要编写代码来创建并等待事件。简要地:
HANDLE event1_done = CreateEvent(...);
HANDLE event2_done = CreateEvent(...);
HANDLE event3_done = CreateEvent(...);
所有事件都是手动重置的,并且它们的初始状态没有信号。
主线程启动三个事件。然后等待第三个完成:
WaitForSingleObject(event3_done, INFINITE);
各个线程进行处理并等待各自的事件。当然,线程 1 不会等待。它只是这样做:
// thread 1
// do processing
// then signal that it's finished
SetEvent(event1_done);
线程 2 进行处理并等待event1_done
,然后设置event2_done
:
// thread 2
// do processing
// wait for the first thread to complete
WaitForSingleObject(event1_done, INFINITE);
// do whatever
// and then signal that it's done
SetEvent(event2_done);
线程 3 与线程 2 类似;只是事件名称发生了变化。
此方法与使用临界区的区别在于多个线程可能正在等待同一个事件对象。当该事件设置时,all等待该对象的线程被释放。如果您只想释放其中一个,那么您可以使用自动重置事件。
另请注意,如果您想重复使用这些事件,则需要重置它们(调用ResetEvent
)。当你这样做时,这取决于你。