我有以下代码:
memoryview
此方法有效,但由于只有一个锁定对象而阻塞了太多-因此,我正在寻找一种命名该锁定对象的方法-以减少竞争。
我尝试了ConcurrentDictionary方法:
private static readonly object cacheLock = new object();
void foo(string key) {
lock(cacheLock) {
// perform calcs on a key
}
}
然后:
class NamedMonitor {
readonly ConcurrentDictionary<string, object> _dictionary = new ConcurrentDictionary<string, object>();
public object this[string name] => _dictionary.GetOrAdd(name, _ => new object());
}
我不喜欢这样做,因为NamedMonitor类中的_dictionary不受限制地增长。
我还尝试了Mutex对象,该对象确实允许命名条目,但是它在操作系统范围内,因此比其他方法慢。
还有哪些其他方法可用于命名锁?理想情况下,我想要这样的代码:
private static NamedMonitor locker = new NamedMonitor();
lock (locker[name]) {
// ...
}
但是我不确定这是否足够安全。
答案 0 :(得分:2)
我建议不要做一些棘手的方法来在集合级别的功能内实现每个密钥级别的状态保护,而是建议您将关注点分离开。根据可以从您的代码片段中推断出的内容,您可以在每个键级别上操作并具有并发性。反过来,这意味着您要保护的每个密钥状态都应该存在(已在某个时候构造)。那么为什么不将这个状态和相应的功能包装到单独的类中,该类另外负责竞争条件下的状态保护,而不是将整个收集状态的更高级别保护与同一单元中的元素级别保护混合在一起,因此看起来如下所示:
public class Item
{
private readonly object _locker = new object();
public void Foo()
{
lock (_locker)
{
// perform calcs
}
}
}
void foo(string key)
{
// the getItem may also require protection but on the collection level
Item item = getItem(key);
item?.Foo();
}
由于每个键的状态已经存在,因此您只需将其包装到类中,该类负责每个键的状态保护并隐式控制锁对象的生命周期。