c# - 为什么 .NET 内部哈希表中有一个 Thread.Sleep(1)?

标签 c# .net hashtable thread-sleep spinwait

最近我在阅读 .NET 的实现 Hashtable并遇到了一段我不明白的代码。部分代码为:

int num3 = 0;
int num4;
do
{
   num4 = this.version;
   bucket = bucketArray[index];
   if (++num3 % 8 == 0)
     Thread.Sleep(1);
}
while (this.isWriterInProgress || num4 != this.version);

整个代码在 System.Collections.Hashtable (mscorlib Version=4.0.0.0) 的 public virtual object this[object key] 中。

问题是:

Thread.Sleep(1) 在那里的原因是什么?

最佳答案

Sleep(1) 是 Windows 中有记录的让出处理器并允许其他线程运行的方法。您可以在带有注释的引用源中找到此代码:

   // Our memory model guarantee if we pick up the change in bucket from another processor,
   // we will see the 'isWriterProgress' flag to be true or 'version' is changed in the reader.
   //
   int spinCount = 0;
   do {
       // this is violate read, following memory accesses can not be moved ahead of it.
       currentversion = version;
       b = lbuckets[bucketNumber];

       // The contention between reader and writer shouldn't happen frequently.
       // But just in case this will burn CPU, yield the control of CPU if we spinned a few times.
       // 8 is just a random number I pick.
       if( (++spinCount) % 8 == 0 ) {
           Thread.Sleep(1);   // 1 means we are yeilding control to all threads, including low-priority ones.
       }
   } while ( isWriterInProgress || (currentversion != version) );

isWriterInProgress 变量是一个可变 bool 值。作者遇到了一些麻烦,英文“violate read”是“volatile read”。基本思想是尽量避免屈服,线程上下文切换非常昂贵,希望作者能尽快完成。如果这没有成功,那么明确让步以避免燃烧 cpu。这在今天可能是用 Spinlock 写的,但 Hashtable 已经很老了。关于内存模型的假设也是如此。

关于c# - 为什么 .NET 内部哈希表中有一个 Thread.Sleep(1)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20006542/

相关文章:

c# - 检查委托(delegate)是否为空

ruby - Ruby 中的符号表溢出问题

c# - 从数据库表中选择两行

c# - .NET 能否在运行时检测到 "irrelevant"代码并对其进行垃圾回收?

c# - 区分来自 2 个独立键盘的输入

.net - MEF 保留 NonShared IDisposable 部分的引用,不允许 GC 收集它们

C# Regex 无法匹配任何内容(可能是因为无法正确转义字符)

c# - 如何查找类实例的通用属性名称以及如何为属性运行时赋值

algorithm - 为什么哈希表平均访问时间不变?

c# - 建议一种针对大型已知集进行颜色模式匹配的算法