如何创建“;命名为互斥访问”;在C#中
本文关键字:访问 命名为 创建 何创建 | 更新日期: 2024-07-23 06:26:14
我有一个基于字符串生成内容的类:
string Produce(string key);
结果被缓存,因此它只生成一个。现在我想锁定生产方法。我只想用这个方法锁定钥匙。。。如果有另一把钥匙进来,它不应该锁上。
我已经从lock
切换到了名为Mutex
的方法,但我读到这种方法很慢,因为Mutex
是操作系统范围的。如何创建某种命名锁?
我正在使用.Net 3.5
一个简单的字符串到对象锁定字典能工作吗?
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());
}
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 "";
}
}
}
对此有一个非常规范的解决方案:
var cacheItems = new ConcurrentDictionary<TKey, Lazy<TValue>>();
...
TValue Get(Func<TValue> factory) {
return cacheItems.GetOrAdd(_ => new Lazy<TValue>(factory)).Value;
}
它具有以下重要特性:
- 它是安全的
- 给定密钥的值只生成一次(对于防止缓存踩踏和节省资源很重要)
- 阅读时无争用
可能会生成多个Lazy
,但只有一个会被强制评估。