ReaderWriterLockSlim出错

时间:2012-04-24 17:45:18

标签: c# multithreading readerwriterlockslim

我得到了这个例外      读取锁定被释放而不被保留          在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();
        }
}  

2 个答案:

答案 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;
}
相关问题