2

我经历了SyncHashtable在.Net框架BCL中定义的实现。

此类提供对多个读取器和写入器的同步访问。

其中一种方法实现为

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;
                }
            }
        }

谢谢维韦克

4

2 回答 2

2

Locking the Hashtable for reading is not necessary because that is already thread safe under these circumstances.

The documentation for Hashtable states:

Hashtable is thread safe for use by multiple reader threads and a single writing thread.

By locking the write access, there is in effect only a single writer, and it is therefore unnecessary to lock reads.

Note that while this is true for Hashtable, it is not the case for Dictionary<TKey, TValue>.

于 2011-06-05T07:52:02.397 回答
0

Not knowing the thread-safety guarantees of the Hashtable I believe you are correct as the lock keyword is a monitor not a implicit reader-writer lock. This could definitely cause undesirable effects. However, given the situation as of today I'd look to the Reactive Extensions for .NET 3.5, it ships with a System.Threading assembly that contains the new concurrent classes as part of the .NET 4.0. These classes are much better suited for dealing with multi-threaded access to collections.

于 2011-06-05T07:51:14.190 回答