多级锁?
Multi level lock?
玩并行处理,我有一个 Parallel.For
循环,它对可枚举对象进行查找,如果找不到它要查找的内容,则添加它。不过,我一直 运行 关注一个线程修改可枚举对象而另一个线程正在执行查找的问题,这会引发异常。显而易见的解决方案是在查找和条目上都使用 lock
,但这有点蛮力。我希望它能够 运行 多个并发查找,所以我不想在一个线程进行查找时完全锁定它,但我确实想禁止它在查找时进行添加正在处理。有没有办法做这样的两级锁?
我会考虑使用某种形式的不可变集合和 Interlocked
来替换共享实例。
例如你提到 "Look ups" 那么 ImmutableDictionary
可能是一个很好的匹配吗?
然后对于查找和更新,你有类似的东西:
var local = sharedReference;
while(!local.ContainsKey(lookupValue))
{
var newValue = /* Whatever */
var newLocal = local.Add(lookupValue,newValue);
var result = Interlocked.CompareExchange(ref sharedReference, newLocal, local);
if(result == local) break;
local = result;
}
//At this point, local definitely contains a key for lookupValue
您可能想要使用 ReaderWriterLock。
private ReaderWriterLockSlim lock = new ReaderWriterLockSlim();
public string Read () {
lock.EnterReadLock ();
try {
return "xxx";
} finally {
lock.ExitReadLock();
}
}
public void Write () {
lock.EnterWriteLock ();
try {
// ...
} finally {
lock.ExiteWriteLock ();
}
}
多个线程可以拥有 ReaderWriterLock 的 "reader" 部分,但只有一个线程可以拥有 "writer" 部分(并且有 writer 时不能有 reader)。
玩并行处理,我有一个 Parallel.For
循环,它对可枚举对象进行查找,如果找不到它要查找的内容,则添加它。不过,我一直 运行 关注一个线程修改可枚举对象而另一个线程正在执行查找的问题,这会引发异常。显而易见的解决方案是在查找和条目上都使用 lock
,但这有点蛮力。我希望它能够 运行 多个并发查找,所以我不想在一个线程进行查找时完全锁定它,但我确实想禁止它在查找时进行添加正在处理。有没有办法做这样的两级锁?
我会考虑使用某种形式的不可变集合和 Interlocked
来替换共享实例。
例如你提到 "Look ups" 那么 ImmutableDictionary
可能是一个很好的匹配吗?
然后对于查找和更新,你有类似的东西:
var local = sharedReference;
while(!local.ContainsKey(lookupValue))
{
var newValue = /* Whatever */
var newLocal = local.Add(lookupValue,newValue);
var result = Interlocked.CompareExchange(ref sharedReference, newLocal, local);
if(result == local) break;
local = result;
}
//At this point, local definitely contains a key for lookupValue
您可能想要使用 ReaderWriterLock。
private ReaderWriterLockSlim lock = new ReaderWriterLockSlim();
public string Read () {
lock.EnterReadLock ();
try {
return "xxx";
} finally {
lock.ExitReadLock();
}
}
public void Write () {
lock.EnterWriteLock ();
try {
// ...
} finally {
lock.ExiteWriteLock ();
}
}
多个线程可以拥有 ReaderWriterLock 的 "reader" 部分,但只有一个线程可以拥有 "writer" 部分(并且有 writer 时不能有 reader)。