Greg, So, from what you are saying, either of these snippets should be valid, right?
> +(id)sharedInstance{ > static id _sharedInstance = nil; > > if (!_sharedInstance){ > @synchronized([self class]){ > if (!_sharedInstance){ > id sharedInstance = [[super allocWithZone:NULL] init]; > OSMemoryBarrier(); > _sharedInstance = sharedInstance; > } > } > } > > OSMemoryBarrier(); > return _sharedInstance; > } vs > +(id)sharedInstance{ > static id _sharedInstance = nil; > > static dispatch_once_t onceToken; > dispatch_once(&onceToken, ^{ > _sharedInstance = [[super allocWithZone:NULL] init]; > }); > > return _sharedInstance; > } Any massive advantages / disadvantages with either approach? -Richard On 08/12/2012, at 4:45:37 PM, Greg Parker <gpar...@apple.com> wrote: > On Dec 8, 2012, at 11:17 AM, Steve Sisak <sgs-li...@codewell.com> wrote: >> At 10:24 AM -0800 12/8/12, Kyle Sluder wrote: >>> On Dec 8, 2012, at 10:06 AM, Steve Sisak <sgs-li...@codewell.com> wrote: >>> >>>> Further, if writes were not complete at the end of the block, the >>>> construct would besentially useless for its intended purpose. >>> >>> By the way, you're wrong about this too. All @synchronized does is act as a >>> mutex around a code block. It does not cause the compiler to reorder >>> instructions and issue memory barriers in such a way that initialization is >>> guaranteed to precede assignment from the perspective of all threads. >> >> Please cite a source for this assertion. > > Source: me, the author of the current @synchronized implementation. > @synchronized performs the same synchronization as a pthread mutex. > > >> From: >> >> <https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html> >> >> "If you are already using a mutex to protect a section of code, do not >> automatically assume you need to use the volatile keyword to protect >> important variables inside that section. A mutex includes a memory barrier >> to ensure the proper ordering of load and store operations." > > To a close approximation, you should pretend that `volatile` does not exist > in C-based languages. > > The above says that if you already have mutexes then you do not need > `volatile`. The mutex alone does all of the work. > > Conversely, `volatile` with no mutex is also not a safe multithreading > pattern. > > >> I acknowledge that, without proper memory barriers, double-checked locking >> is problematic, but am providing an example using a construct which I'm >> fairly sure uses proper memory barriers. >> >> - (NSDictionary *)someDictionary; >> { >> if (!_someDictionary) >> { >> @synchronized (self) >> { >> if (!_someDictionary) >> { >> // create a temp dictionary (might take some time) >> _someDictionary = temp; >> } >> } >> } >> >> return _someDictionary; >> } > > > The example provided does not use proper memory barriers. > > In general, memory barriers need to occur in pairs, one on each thread. The > coordination of the two memory barriers achieves the desired synchronization, > so that both sides observe events occurring in the same order. > > Mutexes and similar constructs achieve this. The mutex lock() and unlock() > procedures form a barrier pair. Code running with the mutex held is therefore > correctly synchronized with respect to other code that runs with the mutex > held. But code running outside the mutex is not protected, because it didn't > call the barrier inside the lock() procedure. > > In faulty double-checked locking code, the problem is that the writer has a > memory barrier but the reader does not. Because it has no barriers, the > reader may observe events occur out of the desired order. That's why it > fails. (Here the "writer" is the thread actually calling the initializer and > the "reader" is a second thread simultaneously performing the double-check > sequence.) > > (Faulty double-checked locking code has a second problem because the > writer-side barrier inside the mutex unlock is the wrong barrier to use with > a reader that is not locking the mutex.) > > You need to do one of two things to fix the reader side of a double-checked > lock: > * add appropriate barriers to the reader side, or > * cheat in a way that is guaranteed to work on all architectures you care > about. > > dispatch_once() actually cheats. It performs a very expensive barrier on the > writer side (much more expensive than the barriers used in ordinary mutexes > and @synchronized), which guarantees that no barrier is needed on the reader > side on the CPUs that run OS X and iOS. The expensive barrier on the reader > side is an acceptable trade-off because the writer path runs only once. > > > -- > Greg Parker gpar...@apple.com Runtime Wrangler > > > > _______________________________________________ > > 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/heardrwt%40gmail.com > > This email sent to heard...@gmail.com _______________________________________________ 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