Reputation: 12624
I know this topic has been pounded as I have read gillions of posts on SO as well as elsewhere about it, but I have yet to find a definitive answer, so my apologies if you are offended by this seeming redundancy.
I have a situation where there is a write-once, read-millions resource. The resource is extremely expensive to create and the contention on the write-lock could be very high as well. Furthermore, I cannot predict what processor this will be run on and so I do not know what the memory-model will be underneath. I am compiling 3 versions of the assembly built in .NET 3.5, .NET 4.0, and Mono 2.10.
Because of the high-contention for the resource, I need to make this as efficient as possible and would like to use a lock-free pattern, at least for the reads. I understand the double lock check pattern for creating the resource, but there has been disagreement over whether or not it works (on all processors) due to the access of _resource outside the memory barrier. Do I need to use volatile on the _resource field? Is a ReaderWriterLockSlim a better fit for this scenario? What other questions should I be asking?
if(_resource == null)
{
lock(_locker)
{
if(_resource == null)
{
//create resource here...
}
}
}
In addition, there will be a number of these:
if(_resource == null)
{
return _resourceDefault;
}
return _resource.GetSomething();
Upvotes: 0
Views: 1717
Reputation: 5261
Decided to promote my comment to an answer.
On creating singleton's read, http://msdn.microsoft.com/en-us/library/ff650316.aspx . It cross links a paper that goes in depth explaining some of the problems related to double checked locking. To be completely safe the microsoft article does recommend the volatile.
A reader writer lock doesn't really buy you anything if all you really just want is to create a singleton (one time thing... no lock promotion or anything is necessary. You really just need to protect creation of the resource). Once the resource is created you won't be touching the lock at all.
I would design access to your singleton to always go through a static property/method so you can always do the double check.
About the resource default, I don't think I know enough about your situation to answer properly. Do you expect the primary resource to ever be null (except before it was created)? Depending on your use case, you might be able to use a Moniter.TryEnter which is nonblocking and returns a value letting you know if you received the lock. If you were not able to immediately get the lock to create the singleton, you could return your default.
Upvotes: 1