【发布时间】:2008-10-01 15:13:58
【问题描述】:
它们似乎都实现了相同的目的。我什么时候会选择一个而不是另一个?
【问题讨论】:
标签: .net multithreading synchronization locking
它们似乎都实现了相同的目的。我什么时候会选择一个而不是另一个?
【问题讨论】:
标签: .net multithreading synchronization locking
当您有一个线程正在等待多个事件中的一个或全部做某事时使用这些事件。
如果您想通过限制可以访问的线程数来限制对数据结构的访问,请使用监视器。
监视器通常保护资源,而事件告诉您正在发生的事情,例如应用程序关闭。
此外,事件可以命名(参见 OpenExisting 方法),这允许它们用于跨不同进程的同步。
【讨论】:
在我看来,如果可以的话,最好使用 Monitor,Monitor.Wait 和 Monitor.Pulse/PulseAll 用于线程之间的信号传输(如 Manual/AutoResetEvent),但是 Monitor 更快,并且不使用本机系统资源。显然 Monitor 是在用户模式下实现并进行管理的,而 Manual/AutoResetEvents 需要切换到内核模式并 p/invoke 到使用等待句柄的本机 win32 调用。
在某些情况下,您需要使用 Manual/AutoResetEvent,例如,在您可以使用命名事件的进程之间发出信号,我猜想在您的应用程序中向本机线程发出信号。
我只是在重复我在this excellent article 中读到的关于线程的内容。
整篇文章都值得一读,但是该链接会将您带到详细说明事件和监控等待/脉冲的等待句柄部分。
【讨论】:
当您希望线程发送或接收二进制信号不需要临界区时,您可以使用WaitHandle。另一方面,Monitor.Wait 和 Monitor.Pulse 需要一个临界区。与 BCL 中的大多数同步机制一样,您提到的两者的使用方式存在一些重叠。但是,暂时不要认为它们实现了相同的目的。
Monitor.Wait 和 Monitor.Pulse 是比 MRE 或 ARE 更原始的同步机制。事实上,您实际上可以使用 Monitor 类来构建 MRE 或 ARE。要理解的最重要的概念是Monitor.Wait 和WaitHandle.WaitOne 方法的不同之处。 Wait 和WaitOne 都将线程置于WaitSleepJoin 状态,这意味着线程变为空闲状态,并且只响应Thread.Interrupt 或各自的Pulse 或Set 调用。但是,这是一个主要区别,Wait 将离开一个临界区并以原子方式重新获取它。 WaitOne 根本无法做到这一点。正是这些同步机制的行为方式的根本差异决定了它们的使用场景。
在大多数情况下,您会选择 MRE 或 ARE。这些满足了一个线程需要从另一个线程接收信号的大多数情况。但是,如果您想创建自己的信号机制,则需要使用Wait 和Pulse。但是,同样,.NET BCL 已经涵盖了大多数流行的信号机制。以下信号机制已经存在1。
1BlockingCollection 类获得了荣誉奖。它本身不是一种信号机制,但它确实具有信号机制的品质,并具有额外的好处,即您可以将数据附加到信号上。在这种情况下,信号表示集合中存在项目,与该信号关联的数据就是项目本身。
【讨论】:
本教程详细说明了您需要了解的内容: http://www.albahari.com/threading/
特别是,这将涵盖 XXXResetEvent 类,
http://www.albahari.com/threading/part2.aspx
这将涵盖 Wait/Pulse : http://www.albahari.com/threading/part4.aspx#_Wait_and_Pulse
【讨论】: