我目前正在使用Hashtable包装为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..
我在这里做了一些有潜在危险的事情,或者这是一个可接受的用例?
答案 0 :(得分:4)
实际上,Hashtable
(与Dictionary<,>
不同)已经具有非常好的线程语义用作缓存:它对读者来说是线程安全的(但需要锁定作者) - from MSDN:
Hashtable是线程安全的,可供多个读取器线程和单个写入线程使用。当只有一个线程执行写(更新)操作时,它对多线程使用是线程安全的,如果编写器被序列化为Hashtable,则允许无锁读取。
(它还提到.Synchronized
支持多个作家,但坦率地自己控制这个通常会给出更好的结果)
但是,为避免幻像读取,您不应使用单独的“包含”/“获取”操作;标准用途可能是(例如使用C#):
public YourType Get(string key) {
return (YourType) expressionCache[key];
}
public void Set(string key, YourType value) {
lock(expressionCache) {
expressionCache[key] = value;
}
}
关键点:
Add
(那么您不需要先检查“包含”)在大多数常见的线程场景中,.Synchronized
包装器的价值实际上非常小。