Name for this template? (Answer: lazy initialization with double lock check)

Consider the following code:

public class Foo { private static object _lock = new object(); public void NameDoesNotMatter() { if( SomeDataDoesNotExist() ) { lock(_lock) { if( SomeDataDoesNotExist() ) { CreateSomeData(); } else { // someone else also noticed the lack of data. We // both contended for the lock. The other guy won // and created the data, so we no longer need to. // But once he got out of the lock, we got in. // There nothing left to do. } } } } private bool SomeDataDoesNotExist() { // Note - this method must be thread-safe. throw new NotImplementedException(); } private bool CreateSomeData() { // Note - This shouldn't need to be thread-safe throw new NotImplementedException(); } } 

Firstly, there are some assumptions that I need to point out:

  • There is a good reason why I couldn’t just do it after starting the application. Perhaps the data is not yet available, etc.

  • Foo can be created and used simultaneously from two or more threads. I want one of them to create some data (but not both of them), then I will allow them to access the same data (ignore the security of data access flows).

  • The cost of SomeDataDoesNotExist () is not huge.

Now this does not have to be limited to some kind of data creation situation, but it was an example that I could think of.

The part I am particularly interested in as a template is checking → lock → check. I had to explain this model several times to developers who did not get the algorithm at first glance, but who could later evaluate it.

In any case, other people should do the same. Is this a standardized sample? What did he call?

+1
source share
4 answers

Lazy initialization with double locking?

+9
source

Although I can see how you think this looks like a double-check lock, what it actually looks like is: a dangerous double-check lock is broken too . Without a real implementation of SomeDataDoesNotExist and CreateSomeData for criticism, we have no guarantee that this thing is actually thread safe for each processor.

For an example of analyzing how a double-check lock might go wrong, check this broken and incorrect version of the double-check lock:

Manual Lock / Unlock C #

My advice: do not use any low-blocking technology for no good reason and review the code from a memory model expert; you are probably mistaken. Most people do.

In particular, do not use double-check locking if you cannot accurately describe what memory access reorders the processors can perform on your behalf and provide a convincing argument in favor of the correct solution, given any possible memory access reordering. At that moment, when you are a bit away from the known implementation, you need to start the analysis from scratch. You cannot assume that just because one double-check lock implementation is correct that all of them are; almost none of them are correct.

+13
source

The part that I'm particularly interested in as a template is the check -> lock -> check.

This is called a double-checked lock .

Beware that in older versions of Java (prior to Java 5) this is not safe due to how the Java memory model was defined. In Java 5 and newer changes have been made to the specification of the Java memory model, so now it is safe.

+4
source

The only name that comes to mind for this kind is Fault. This name is used in iOS Core-Data for a similar effect.

Basically, your NameDoesNotMatter method is a mistake, and whenever someone calls it, it causes the object to become filled or initialized.

For more information on how this design pattern is used, see http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdFaultingUniquing.html .

0
source

All Articles