Hashtable.Synchronized是否适合用作多线程环境中的简单缓存



我目前正在使用一个包装为哈希表的哈希表。在多线程环境(如asp.net)可以使用的库中作为简单缓存同步-这适合用于此集合吗?我知道.Net 4.0中有更合适的结构,但我一直使用.Net 3.5。

如果有什么不同的话,这个缓存会经常被读取,并且很少被写入(但需要保持线程安全)。

基本用法大致如下:

Private Shared ReadOnly ExpressionCache As Hashtable = Hashtable.Synchronized(New Hashtable())
..snip...
If Not ExpressionCache.ContainsKey(myKey) Then
ExpressionCache(myKey) = myExpensiveOperationToInit()
End If
Return  ExpressionCache(myKey)
..snip..

我是在做一些潜在危险的事情,还是这是一个可以接受的用例?

实际上,Hashtable(与Dictionary<,>不同)已经具有非常好的线程语义,可以用作缓存:它对阅读器是线程安全的(但需要锁定写入程序)-来自MSDN:

哈希表是线程安全的,可供多个读取器线程和单个写入线程使用。当只有一个线程执行写(更新)操作时,多线程使用是线程安全的,这允许无锁读取,前提是写入程序被序列化到哈希表。

(它还提到.Synchronized支持多个作者,但坦率地说,我们自己控制它通常会得到更好的结果)

但是,为了避免幻影读取,您不应该使用单独的"contains"/"get"操作;标准用法可能是(例如使用C#):

public YourType Get(string key) {
return (YourType) expressionCache[key];
}
public void Set(string key, YourType value) {
lock(expressionCache) {
expressionCache[key] = value;
}
}

要点:

  • 只有"set"有任何锁定
  • "get"中只有一个操作
  • 在集合中使用索引器,而不是Add(这样就不需要先检查"包含")

.Synchronized包装器在大多数常见的线程场景中实际上没有什么价值。

相关内容

最新更新