Is Hashtable.Synchronized suitable for use as a simple cache in a multithreaded environment?

99封情书 提交于 2021-02-05 08:48:06

问题


I'm currently using a Hashtable wrapped as a Hashtable.Synchronized as a simple cache in a library that could be used by a multi-threaded environment (such as asp.net) - is this a suitable use for this collection? I understand that there are more suitable constructs available in .Net 4.0, but I'm stuck with .Net 3.5.

If it makes any difference, this cache is read from frequently, and is written to very infrequently (but needs to remain threadsafe).

Basic usage is something along the lines of:

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..

Am I doing something potentially dangerous here, or is this an acceptable use case?


回答1:


Actually, Hashtable (unlike Dictionary<,>) already has very good threading semantics for use as a cache: it is thread-safe for readers (but requires locking for writers) - from MSDN:

Hashtable is thread safe for use by multiple reader threads and a single writing thread. It is thread safe for multi-thread use when only one of the threads perform write (update) operations, which allows for lock-free reads provided that the writers are serialized to the Hashtable.

(it also mentions .Synchronized for supporting multiple writers, but frankly taking control of this ourselves usually gives much better results)

However, to avoid phantom reads, you shouldn't use separate "contains" / "get" operations; standard use might be (using C# for the example):

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

key points:

  • only the "set" has any locking
  • only a single operation in the "get"
  • use the indexer, not Add, in the set (then you don't need to check "contains" first)

The .Synchronized wrapper is actually of remarkably little value in most common threading scenarios.



来源:https://stackoverflow.com/questions/12554803/is-hashtable-synchronized-suitable-for-use-as-a-simple-cache-in-a-multithreaded

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!