Hashtable.Synchronized是否适合用作多线程环境中的简单缓存? [英] Is Hashtable.Synchronized suitable for use as a simple cache in a multithreaded environment?

查看:43
本文介绍了Hashtable.Synchronized是否适合用作多线程环境中的简单缓存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用包装为Hashtable的Hashtable.Synchronized作为可在多线程环境(例如asp.net)中使用的库中的简单缓存-这是否适合此集合?我了解到.Net 4.0中提供了更多合适的结构,但是我对.Net 3.5感到困惑.

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

基本用法类似于:

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?

推荐答案

实际上,哈希表(不同于 Dictionary<,> )已经具有非常好的线程语义可供使用作为缓存:对于阅读器是线程安全的(但需要锁定写作者)-

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是线程安全的,可供多个读取器线程和一个写入线程使用.当只有一个线程执行写(更新)操作时,它对于多线程使用是线程安全的,只要将写程序序列化到Hashtable,就可以进行无锁读取.

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.

(它还提到了 .Synchronized 以支持多个编写者,但坦率地说,通常自己控制它会带来更好的结果)

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

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

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

要点:

  • 只有集合"具有任何锁定
  • 获取"中只有一个操作
  • 在集合中使用索引器,而不是 Add (然后您无需先检查包含")
  • 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)

.synchronized 包装器实际上在大多数常见的线程方案中价值不大.

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

这篇关于Hashtable.Synchronized是否适合用作多线程环境中的简单缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆