Error with ReaderWriterLockSlim

I got this exception A read lock is released without a hold.
in System.Threading.ReaderWriterLockSlim.ExitReadLock () at .. GetBreed (String)

Below is the only place in the code that accesses locking. As you can see, there is no recursion. I am having trouble understanding how this exception could have happened.

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(); } } 
+8
multithreading c # readerwriterlockslim
source share
2 answers

I assume that you have something repetitive and it throws an exception when it gets a lock. Is there a trick-22 if you “take the lock”, “try” against “try”, “take the lock”, but “take the lock”, “try”, has fewer failures (“interrupted between try” is so disappearingly unlikely that you don’t need stress).

Move “take lock” outside of “try” and see what the actual exception is.

The problem, most likely, is that you cannot lock the lock (possibly redirect), and then try to unlock something that you did not accept. This may mean that the exception surfaces in the original code that took the lock are due to attempts to release twice when only once.

Note. The monitor has new overloads with "ref bool" parameters to help with this scenario, but not with other types of locks.

+3
source share

Use LockRecursionPolicy.SupportsRecursion when creating an RWLS instance. If the error goes away, you really have some sort of recursion. Perhaps this is code that you did not publish?

And if you are really worried that you will get the most concurrency from this (as I suspect you have been using RWLS ever since), you can use a double-check lock pattern. Note that your source code already has this feeling? So why beat around the bush? Just do it.

In the following code, note that I always consider the Breeds link to be immutable, and then inside the lock I double-check, copy, modify, and replace the link.

 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; } 
+3
source share

All Articles