8

我得到了这个异常
读取锁正在被释放而不被持有。
在 System.Threading.ReaderWriterLockSlim.ExitReadLock() 在 .. 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();
        }
}  
4

2 回答 2

3

我猜你有一些可重入的东西,它在获取锁时会抛出异常。无论您“获取锁”、“尝试”还是“尝试”、“获取锁”都有一个 catch-22,但是“获取锁”、“尝试”的失败案例较少(“获取和尝试”是非常不可能的,你不需要强调)。

将“取锁”移到“尝试”之外,看看实际的异常是什么。

问题很可能是你没有拿锁(可能是重新进入),然后试图解锁你没有拿的东西。这可能意味着在获取锁的原始代码中出现异常,因为在只获取一次时尝试释放两次。

注意:监视器具有带有“ref bool”参数的新重载来帮助解决这种情况 - 但不是其他锁类型。

于 2012-04-24T18:00:44.237 回答
3

LockRecursionPolicy.SupportsRecursion在实例化 RWLS 时使用。如果错误消失,那么您实际上确实涉及某种类型的递归。也许是您没有发布的代码?

如果你真的很关心从中获得最大的并发性(我怀疑你是因为你使用的是 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;
}
于 2012-04-24T18:48:36.320 回答