On Dec 7, 2012, at 10:18 PM, Steve Sisak wrote:

> At 8:57 PM -0600 12/7/12, Ken Thomases wrote:
>> > the outer if avoids the overhead of @synchronized if _someDictionary is 
>> > already created -- this is just an optimization
>>> 
>>> the inner if is necessary to resolve the race condition if multiple threads 
>>> make it past the outer one
>> 
>> This is a classic anti-pattern called double-checked locking.  It is not 
>> safe.  Don't rely on it.
>> https://en.wikipedia.org/wiki/Double-checked_locking
>> http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf
> 
> Hi Ken,
> 
> From the first link you cite:
> 
>> The pattern, when implemented in some language/hardware combinations, can be 
>> unsafe. At times, it can be considered an anti-pattern.[2]
> 
> That is far different from being a "a classic anti-pattern".

So Wikipedia waffled.  That doesn't make what I said false.  Double-checked 
locking is widely regarded as unsafe in C-based languages.  Only in certain 
languages which have much stronger memory models than C can it be made safe.  
If in doubt, avoid it.


> In this example:
> 
> 1) The language is Obj-C

That's part of the problem.  Objective-C is a C-based language and doesn't have 
any stronger guarantees about the memory model than C.  If we were working in 
Java, you might be safe.

> 2) I explicitly used @synchronized(self) and an instance variable

So?  The use of a lock is exactly part of the double-checked _locking_ 
technique.  It doesn't make it safe, it only makes it seem safe. Do you imagine 
that @synchronized is fundamentally different than any other locking mechanism, 
such as a pthreads mutex?

> So, in this case, what I'm doing is explicitly supported by the language.

Nope.  The compiler, the CPU, and/or the cache can reorder the execution (or 
apparent execution) of the instructions within the lock such that the check 
that's outside of the lock will skip the lock even though the object hasn't 
been created and fully initialized yet.

The problem is precisely that the first check is outside of the lock and 
outside of any protection provided by memory barriers.

> Your second article is explicitly focused on C++ (and singletons) -- it's 
> also dated 2004.

It explains the principles that are applicable to all C-based languages (and 
even addresses Java).  And the fact that it's from 2004 doesn't make it wrong.  
The passage of time didn't erode its accuracy.

It also directly explains that they used the implementation of a singleton as 
an example but that the problems with double-checked locking are not specific 
to singletons.

> On Mac OS X, the correct implementation of a singleton is dispatch_once() -- 
> in fact, that is the function's raison d'ĂȘtre.

The function's raison d'ĂȘtre is not singletons, it's doing something once and 
only once.

It's also the correct mechanism for what you're using double-checked locking 
for.

> So, while I support the position that double-checked locking can be unsafe in 
> con language/hardware combination, in this case we're using language features 
> specifically designed for the purpose.

No, you're not.  Since you're checking the instance variable outside of the 
lock, and failing to take the lock based on its state, you are not using the 
lock in all cases.

Regards,
Ken


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to