我有一个基于字符串生成东西的类:
string Produce(string key);
结果是缓存的,因此只生成一个。现在我想锁定生产方法。我只希望方法锁定密钥......如果另一个密钥进入,它不应该锁定。
我已从lock
切换到命名Mutex
,但我读到这个方法很慢,因为Mutex
是操作系统范围的。我将如何创建一些命名锁?
我正在使用.Net 3.5
答案 0 :(得分:2)
对象锁定字典的简单字符串是否有效?
object _superLock = new object();
Dictionary<string, object> _locks = new Dictionary<string, object>();
string Produce(string key) {
lock(GetLock(key)) {
// do stuff
}
}
object GetLock(string key) {
lock(_superLock) {
if (!_locks.ContainsKey(key)) {
_locks[key] = new object();
}
}
return _locks[key];
}
更新:哦,对了,ConcurrentDictionary存在。这可能看起来像
ConcurrentDictionary<string, object> _locks = new ConcurrentDictionary<string, object>();
object GetLock(string key) {
return _locks.GetOrAdd(key, k => new object());
}
答案 1 :(得分:1)
ConcurrentDictionary
让这很容易:
public class Foo
{
private ConcurrentDictionary<string, object> locks =
new ConcurrentDictionary<string, object>();
public string Produce(string key)
{
lock (locks.GetOrAdd(key, new object()))
{
//TODO do whatever
return "";
}
}
}
答案 2 :(得分:0)
这有很多规范的解决方案:
var cacheItems = new ConcurrentDictionary<TKey, Lazy<TValue>>();
...
TValue Get(Func<TValue> factory) {
return cacheItems.GetOrAdd(_ => new Lazy<TValue>(factory)).Value;
}
这具有以下重要属性:
可能会产生多个Lazy
,但只有一个会被迫评估。