views:

237

answers:

1

Hello i need to user writerreaderlock in my method. I want to know how use it correctly.

I got a dictionnary of ObjectA

public class ObjectA
{
public ReaderWriterLock RWL {get;set;}
public ObjectB obj {get;set;}
public ObjectA()
{
RWL = new ReaderWriterLock();
}

}

public class ObjectB
{
int TTL {get;set;}
string Value {get;set;}
}

In my method I user a dictionnary of ObjectA, the key is a Guid, so presume that when i call dict[guid] return always an instance of my ObjectA (for the exemple)

public foo()
{

ObjecA objA = dict[guid];
objA.RWL.AcquireReaderLock(500);
if(objA.obj.TTL<=0)
{
objA.obj.RWL.AcquireWriterLock(1000);
objA.obj.Value = DateTime.Now().ToString();
objA.obj.RWL.ReleaseWriterLock();

}else{
 int ttl = objA.obj.TTL;
 Interlocked.Decrement(ref ttl);
}    
objA.RWL.ReleaseReaderLock();
}

I am relly not sure of my using of reader and writer over there, how did i need to use reader writer lock, with a conditional validation ?

+5  A: 

There are many problems with this code, including:

  • you're not actually ever decrementing the TTL in your class instance-- as Nikolai points out, you're decrementing a local variable! Interlocked.Decrement(ref objA.obj.TTL) is how to do this properly.
  • you're not setting an initial TTL value, so it will always be zero (unless some other code is setting it, which is probably not wise for a threading-sensitive class where you generally want all thread-safety-related code in the same class to avoid losing track of who is doing what)
  • you should be using ReaderWriterLockSlim, which is now preferred to the older ReaderWriterLock class. See the latter hyperlink for why.
  • when acquiring a write lock, if you already have a read lock, you'll need to upgrade your lock-- there's usually a separate method on the lock class for that. Similarly, after you upgrade, releasing the lock requires one method to release the lock, not one to release the write lock and another to release the previous read lock.
  • you'll need to deal with the failure case where you are unable to acquire locks.
  • you'll want to wrap code in using or try/finally blocks to ensure that resources are freed even if an exception occurs.

It also may be worth considering whether you really, really need to use reader/writer locks, instead of using something simpler like the lock{} statement. Getting reader/writer locks right and avoiding deadlocks is hard even for developers who know these APIs and concepts really well, and even then they usually reserve their use for only the most performance-critical places (1000's+ per second). In other words, you may be better off starting out with a simpler approach using lock{}, and only falling back to using ReaderWriterLockSlim if performance is not acceptable.

As a starting point, I'd suggest you add some more info to your question:

  • first, include a high-level description of what you're trying to do, including high-level requirements for functionality and performance. this can help us recommend the right solution and to know if reader/writer lock is the right approach.
  • try to write out, in pseudo-code or just plain english, exactly how you want your code to behave, including how you want to address the logical issues above (e.g. what to do when a timeout happens, how is TTL set, etc.)
  • revise your code sample to include fixes for some/all of the problems I noted above

I guarantee you that if you include this addiitonal info in your question, you'll get better answers which can help you out with any any remaining code issues. :-)

Justin Grant
Thanks for your answer, but the code i show was only an exemple, i used my code in a HttpHandler, a lock is really to slow for my web application. I will try with ReaderWriterLockSlim Thanks. I find i could uprade my readerlock to a writerlock, and that information will help me. Thanks
Cédric Boivin
Excellent answer - very helpful!
torial