2011-06-05 69 views
2

我经历了在.Net框架BCL中定义的SyncHashtable的实现。SyncHashtable this [对象键]不使用锁定

此课程提供对多个读者和作者的同步访问。

其中一种方法被实现为

public override Object this[Object key] { 
      get { 
        return _table[key]; 
      } 
      set { 
       lock(_table.SyncRoot) { 
        _table[key] = value; 
       } 
      } 
     } 

在我看来GET方法还应该访问对象之前对SyncRoot上的锁。

考虑场景:

线程1:从Hashtable删除键。

线程2:使用键读取对象。

如果在读取对象时线程2发生上下文切换,并且线程1删除了该对象,则在这种情况下,读取操作将失败或导致不一致的结果。

因此,我们不能把实现这样

public override Object this[Object key] { 
      get { 
       lock(_table.SyncRoot) 
        { 
        return _table[key]; 
        } 
      } 
      set { 
       lock(_table.SyncRoot) { 
        _table[key] = value; 
       } 
      } 
     } 

由于这种方法 维韦克

回答

2

Hashtable锁定为阅读不是必要的,因为在这种情况下,它已经是线程安全的。

Hashtable状态的文档:

Hashtable是线程安全的被多个读线程和一个写线程使用。

通过锁定写访问,实际上只有一个写入器,因此不必锁定读取。

请注意,虽然这是Hashtable,但它是而不是的情况下为Dictionary<TKey, TValue>

+0

我没有调用Hashtable线程安全;我重复了文档,因为它对于特定场景(多个读者和一个作者)是线程安全的。这反过来使得SyncHashtable线程安全无需锁定读取。 – Sven 2011-06-05 07:59:37

+0

我只是想用不同的方式来表达,现在我认为这可能是没有必要的。我删除了原来的评论。 – 2011-06-05 08:04:59

0

不知道Hashtable我相信你是正确的线程安全保证为锁定关键字是一个监视器不是一个隐含的读写器锁。这肯定会造成不良影响。然而,考虑到今天的情况,我会看看.NET 3.5的Reactive Extensions,它附带了一个System.Threading程序集,它包含作为.NET 4.0一部分的新并发类。这些类更适合处理对集合的多线程访问。

+0

正如我在我的回答中所说的,Hashtable对多个读者和一个作者是线程安全的,所以没有必要锁定。 但是,如果可能的话,我会同意你的建议来使用ConcurrentDictionary 。 – Sven 2011-06-05 07:54:39