private const int s_spinCount = 4000;
public void Wait()
{
SpinWait s = new SpinWait();
while (m_remain > 0)
{
if (s.Spin() >= s_spinCount) m_event.WaitOne();
}
}
不可否认,选择频率和旋转计数是不确定的。与 Win32 临界区旋转计数类似,我们应
该根据测试和实验的结果来选择合理的数值,而且即使合理的数值在不同系统中也会发生变
化。例如,根据 Microsoft Media Center 和 Windows kernel 团队的经历,MSDN 文档建议临
界区旋转计数为 4,000 ,但您的选择可以有所不同。理想的计数取决于多种因素,包括在
给定时间等待事件的线程数和事件出现的频率等。大多数情况下,您会希望通过等待事件来
消除显式让出时间,如锁存的例如中所示。
您甚至可以选择动态调整计数:例如,从中等数量的旋转开场,每次旋转失败就增加计数。
一旦计数到达预定的最大值,就完全停顿旋转并立即发出 WaitOne。逻辑如下所示:您希望
立即增加到达预定的最大周期数,但却无法超过最大周期数。如果您发现此最大值缺乏以阻
止上下文切换,那么立即执行上下文切换总的算来占用的资源更少。慢慢您就会希望旋转计
数能够到达一个稳定的值。
三、屏障 (Barrier)
屏障,又称集合点,是一种并发性基元,它无需另一“主〞线程控制即可实现各线程之
间简单的互相协调。每个线程在到达屏障时都会不可再分地发出信号并等待。仅当所有 n
都到达屏障时,才允许所有线程继续。这种方法可用于协调算法 (cooperative algorithms),
该算法广泛应用于科学、数学和图形领域。很多计算中都适合使用屏障,实际上,甚至 CLR
的垃圾收集器都在使用它们。屏障只是将较大的计算分割为假设干较小的协作阶段
(cooperative phase),例如:
const int P = ...;
Barrier barrier = new Barrier(P);
Data[] partitions = new Data[P];