【问题标题】:Is Hashtable.Synchronized suitable for use as a simple cache in a multithreaded environment?Hashtable.Synchronized 是否适合在多线程环境中用作简单缓存?
【发布时间】:2012-09-15 07:25:03
【问题描述】:

我目前正在使用包装为 Hashtable 的 Hashtable。同步作为库中的一个简单缓存,可供多线程环境(例如 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..

我在这里做了一些潜在危险的事情吗,或者这是一个可以接受的用例?

【问题讨论】:

    标签: .net collections hashtable


    【解决方案1】:

    实际上,Hashtable(与 Dictionary<,> 不同)已经具有非常好的线程语义,可用作缓存:它对于 readers 来说是线程安全的(但需要为 writers 锁定)-@987654321 @:

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

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

    但是,为避免幻读,您不应使用单独的“包含”/“获取”操作;标准用法可能是(以 C# 为例):

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

    关键点:

    • 只有“集合”有任何锁定
    • “get”中只有一个操作
    • 在集合中使用索引器,而不是Add(那么您不需要先检查“包含”)

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

    【讨论】:

    • 感谢您提供的非常有帮助的答案;只是为了澄清 - 我在多线程场景中使用 .Synchronized 包装器是否有任何错误?即使它不是最优化的方法?
    • @DanP 不,它会起作用 - 但是:如果你小心的话,你可以无锁地读取。或者可能是双重检查锁定,即var tmp = (YourType)expressionCache[key]; if(tmp == null) lock(expressionCache) { tmp = (YourType)expressionCache[key]; if(tmp == null) { tmp = GetNewValue(); expressionCache[key] = tmp;} } return tmp;
    • @Blam Dictionary<,> 不支持“7 个读者加 1 个作者”的场景 - 尽管它支持“7 个读者”(独家)“1 个作者” .这意味着如果您使用Dictionary<,> 执行此操作,您要么必须使用完全排他锁(例如lock aka Monitor),要么使用类似ReaderWriterLockSlim 的东西。 Hashtable 可能的无锁方法更具可扩展性。
    猜你喜欢
    • 2019-10-14
    • 2011-11-13
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    相关资源
    最近更新 更多