这个要求相当简单:我想确保多个线程不会同时修改一个对象。棘手的部分是,对象来自一个工厂,其实现在运行时之前是未知的。它可以返回单个实例,可以每次创建一个新实例,也可以有一个共享实例池。
var thing = factory.Get(...);
lock (???) {
// modify thing
}
我理解锁定其他代码可能锁定的公开可见对象是不安全的,因此可能导致死锁。换句话说,我不应该
lock (thing)
. 但理想情况下我想锁定
某物
相同,仅在运行时范围内已知
thing
.
我提出的一个潜在解决方案是使用
ConcurrentDictionary
由键控的对象
事情
的哈希代码:
private static ConcurrentDictionary<int, object> _thingLocks =
new ConcurrentDictionary<int, object>();
...
var thing = factory.Get(...);
var thingLock = _thingLocks.GetOrAdd(thing.GetHashCode(), new object())
lock (thingLock) {
// modify thing
}
凭直觉,我认为这应该是可行的,因为a)锁本身是私有的,所以没有外部的东西可以锁定它们,b)锁实例是
极有可能
*1比1
事情
实例。但由于这类代码很难测试,我想问:这是正确和适当的解决方案吗?对于仅在运行时才知道的作用域,是否有更好/首选的锁定方法?
*-正如评论中所指出的,这并不能保证,但在不太可能发生碰撞的情况下,这仅仅意味着2
事情
不能同时修改S,这是不理想的,但完全安全。