我得到了这个例外 读取锁定被释放而不被保留 在System.Threading.ReaderWriterLockSlim.ExitReadLock() at .. GetBreed(String)
以下是访问锁定的代码中唯一的位置。如您所见,没有递归。我无法理解如何发生此异常。
static readonly Dictionary<string, BreedOfDog> Breeds
= new Dictionary<string,BreedOfDog>();
static BreedOfDog GetBreed(string name)
{
try
{
rwLock.EnterReadLock();
BreedOfDog bd;
if (Breeds.TryGetValue(name, out bd))
{
return bd;
}
}
finally
{
rwLock.ExitReadLock();
}
try
{
rwLock.EnterWriteLock();
BreedOfDog bd;
//make sure it hasn't been added in the interim
if (Breeds.TryGetValue(t, out bd)
{
return bd;
}
bd = new BreedOfDog(name); //expensive to fetch all the data needed to run the constructor, hence the caching
Breeds[name] = bd;
return bd;
}
finally
{
rwLock.ExitWriteLock();
}
}
答案 0 :(得分:3)
我猜你有一些可重入的东西,并且在获得锁定时会抛出异常。有一个catch-22你是否“采取锁定”,“尝试”vs“尝试”,“采取锁定”,但“采取锁定”,“尝试”有更少的失败案例(“中止和尝试“你不太可能不需要压力”。
将“取消锁定”移到“尝试”之外,看看实际例外是什么。
问题很可能是你没有锁定(可能是重新入侵),然后尝试解锁你没有拿走的东西。这可能意味着, orginal 代码中的异常表面会导致锁定,因为尝试在仅执行一次时释放两次。
注意:Monitor有“ref bool”参数的新重载来帮助解决这个问题 - 但不是其他锁类型。
答案 1 :(得分:3)
在实例化RWLS时使用LockRecursionPolicy.SupportsRecursion
。如果错误消失,那么你实际上确实涉及某种类型的递归。也许是你没有发布的代码?
如果您真的担心获得最大并发性(因为我怀疑您使用的是RWLS),那么您可以使用双重检查锁定模式。请注意您的原始代码对此有何感觉?那么为什么要绕着丛林?就这么做。
在下面的代码中,请注意我总是将Breeds
引用视为不可变,然后在lock
内部重新检查,复制,更改和交换引用。
static volatile Dictionary<string, BreedOfDog> Breeds = new Dictionary<string,BreedOfDog>();
static readonly object LockObject = new object();
static BreedOfDog GetBreed(string name)
{
BreedOfDog bd;
if (!Breeds.TryGetValue(name, out bd))
{
lock (LockObject)
{
if (!Breeds.TryGetValue(name, out bd))
{
bd = new BreedOfDog(name);
var copy = new Dictionary<string, BreedOfDog>(Breeds);
copy[name] = bd;
Breeds = copy;
}
}
}
return bd;
}