在读的时候 C# 3.0 简而言之 经过 约瑟夫和本阿尔巴哈里, ,我遇到了以下段落(第 673 页,标题为“使用等待和脉冲发送信号")

“这 监视器 类通过两个静态方法提供另一个信号构造, 等待脉冲. 。原则是您自己使用自定义标志和字段(包含在 语句),然后引入 等待脉冲 用于减轻 CPU 旋转的命令。这种低级方法的优点是只需 等待, 脉冲, ,以及 语句,可以实现的功能 自动重置事件, 手动重置事件, , 和 信号, , 也 等待句柄的静态方法 等待所有等待. 。此外, 等待脉冲在所有等待手柄均受到挑战的情况下,可以适合。”

我的问题是,正确的解释是什么 最后的 句子?

  • 具有大量等待句柄的情况,其中仅偶尔对任何特定等待句柄调用 WaitOne()。
  • 一种具有大量等待句柄的情况,其中很少有多个线程倾向于在任何特定等待句柄上阻塞。
  • 其他一些解释。

还希望了解此类情况的启发性示例,以及如何和/或为什么通过等待和脉冲而不是其他方法更有效地处理它们。

谢谢你!

编辑:我在网上找到了这段文字 这里

有帮助吗?

解决方案

这意味着在某些情况下,Wait 和 Pulse 提供了比等待句柄更简单的解决方案。一般来说,这种情况发生在:

  • 服务员而不是通知者决定何时解锁
  • 阻塞条件涉及的不仅仅是一个简单的标志(可能是几个变量)

在这些情况下,您仍然可以使用等待句柄,但 Wait/Pulse 往往更简单。Wait/Pulse 的伟大之处在于 Wait 在等待时释放底层锁。例如,在下面的示例中,我们在锁的安全范围内读取 _x 和 _y - 然而该锁在等待时被释放,以便另一个线程可以更新这些变量:

lock (_locker)
{
  while (_x < 10 && _y < 20) Monitor.Wait (_locker);
}

然后另一个线程可以原子地更新 _x 和 _y (凭借锁),然后用 Pulse 向服务员发出信号:

lock (_locker)
{
  _x = 20;
  _y = 30;
  Monitor.Pulse (_locker);
} 

等待/脉冲的缺点是更容易出错并犯错误(例如,更新变量并忘记脉冲)。在具有等待句柄的程序与具有等待/脉冲的程序同样简单的情况下,出于这个原因,我建议使用等待句柄。

就效率/资源消耗而言(我认为您提到了这一点),等待/脉冲通常更快、更轻(因为它具有托管实现)。不过,这在实践中很少有什么大不了的。在这一点上,Framework 4.0 包括 ManualResetEvent 和 Semaphore 的低开销托管版本(ManualResetEventSlim 和 SemaphoreSlim)。

Framework 4.0 还提供了更多同步选项,减少了对 Wait/Pulse 的需求:

  • 倒计时活动
  • 障碍
  • PLINQ / 数据并行性(AsParallel、Parallel.Invoke、Parallel.For、Parallel.ForEach)
  • 任务和延续

所有这些都比 Wait/Pulse 级别高得多,并且 IMO 更适合编写可靠且可维护的代码(假设它们将解决手头的任务)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top