upgradable reader lock in c#
I have a dictionary that is shared among number of threads. Every thread reads specific value from the dictionary according to a given key, but - if the key does not exist in the dictionary the thread need to add it to the dictionary.
To solve the sync problem, I though to use ReaderWriterLockSlim class which basically gives me readers-writers lock synchronization (meaning readers can run in parallel but only one writer at a time开发者_C百科...) but adds upgrade option for a reader. Using the upgrade option I can test whether a given key is already in the dictionary and if not - upgrade the lock and write it, promising only one addition for every key.My problem is that I cant create two upgradeable locks at a time - meaning this solution is no good... :(
Can somebody please explain to me why Microsoft chose to implement the upgradable lock this way (that I cant have more than one upgradable lock at a time...), and give me any idea how can I implement the upgradable lock by myself \ give me another idea to sync my shared dictionary?
If you are using .NET 4.0 why not use the ConcurrentDictionary
I have no idea why ReaderWriterLockSlim
was implemented in that way. I suspect there are good reasons.
Why not just use ConcurrentDictionary? Then you don't have to worry about explicit locking.
That said, I don't see where having multiple upgradable reader locks would help you. Consider the following scenario:
Thread1 enters the lock in upgradeable mode
Thread2 enters the lock in upgradeable mode
Thread1 searches for "xyzzy" and doesn't find it
Thread2 searches for "xyzzy" and doesn't find it
Thread2 upgrades to a write lock
Thread1 waits to upgrade to a write lock
Thread2 updates and releases the lock
Thread1 acquires the write lock and overwrites what Thread2 had written
In order to prevent Thread1 from overwriting what Thread2 did, you'd have to write this logic:
Enter upgradable read lock
if (!dict.TryGetValue(...))
{
Enter write lock
if (!dict.TryGetValue(...)) // extra check required!
{
}
}
Which is exactly what you have to do when there are no upgradeable locks.
UpgradeableReadLock exists so you do not have to release your read lock prior to acquiring a write lock. It lets you do this:
locker.EnterUpgradeableReadLock();
...
locker.EnterWriteLock();
...
instead of
locker.EnterReadLock();
...
locker.ExitReadLock();
locker.EnterWriteLock();
...
As it is a ReaderWriter lock, you may still only have one writer at any given time, which an upgradeable read lock enforces. This means these two aren't equivalent; the first lets other callers sneak in, but allows concurrency in the read portion.
If you have cases where you can use ReadLocks for most reads, and UpgradeableRead for data updates/inserts, this is the intent. If all of your data accesses are potential writers, then this probably doesn't work as well and you can use simple lock(object) around your writes to enforce the exclusive access when adding/updating.
It doesn't sound like you are perhaps using the optimal solution to this problem.
Example:
protected static object _lockObj = new object();
if(_dictionary.ContainsKey(key))
{
return _dictionary[key];
}
else
{
lock(_lockObj)
{
if(_dictionary.ContainsKey(key))
return _dictionary[key];
_dictionary.Add(key, "someValue");
return "someValue";
}
}
If you're using .NET 4, try using the ConcurrentDictionary class that others have mentioned.
精彩评论