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