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

Reply via email to