Thread safe instantiation of a singleton

前端 未结 5 2099
栀梦
栀梦 2020-12-04 08:28

Which one synchronization method to use to ensure a singleton remains a singleton?

+(Foo*)sharedInstance
{
   @synchronized(self)
   {
      if (nil == _shar         


        
5条回答
  •  醉酒成梦
    2020-12-04 08:41

    If anyone cares, here is another macro for the same thing :)

    IMHO, it provides greater flexibility compared to the other variations.

    #define SHARED_INSTANCE(...) ({\
        static dispatch_once_t pred;\
        static id sharedObject;\
        dispatch_once(&pred, ^{\
            sharedObject = (__VA_ARGS__);\
        });\
        sharedObject;\
    })
    

    Usage, one-line initialization:

    + (instancetype) sharedInstanceOneLine {
        return SHARED_INSTANCE( [[self alloc] init] );
    }
    

    Usage, multi-line initialization (notice curly braces around the block of code):

    + (instancetype) sharedInstanceMultiLine {
        return SHARED_INSTANCE({
            NSLog(@"creating shared instance");
            CGFloat someValue = 84 / 2.0f;
            [[self alloc] initWithSomeValue:someValue]; // no return statement
        });
    }
    

    Usage in the right part of an assignment:

    - (void) someMethod {
        MethodPrivateHelper *helper = SHARED_INSTANCE( [[MethodPrivateHelper alloc] init] );
        // do smth with the helper
    }
    // someMethod should not call itself to avoid deadlock, see bbum's answer
    

    This modification utilizes two language features: the GCC compound expressions extension, which is also supported by Clang, and the C99 variadic macros support.

    After pre-processing, the output will look like (you can test it yourself by invoking Product > Perform Action > Preprocess "YourClassName.m" in Xcode 5):

    + (instancetype) sharedInstanceOneLine {
        return ({
            static dispatch_once_t pred;
            static id sharedObject;
            dispatch_once(&pred, ^{
                sharedObject = ( [[self alloc] init] );
            });
            sharedObject; // this object will be returned from the block
        });
    }
    
    + (instancetype) sharedInstanceMultiLine {
        return ({
            static dispatch_once_t pred;
            static id sharedObject;
            dispatch_once(&pred, ^{
                sharedObject = ({
                    NSLog(@"creating shared instance");
                    CGFloat someValue = 84 / 2.0f;
                    [[self alloc] initWithSomeValue:someValue];
                });
            });
            sharedObject;
        });
    }
    
    - (void) someMethod {
        MethodPrivateHelper *helper = ({
            static dispatch_once_t pred;
            static id sharedObject;
            dispatch_once(&pred, ^{
                sharedObject = ( [[MethodPrivateHelper alloc] init] );
            });
            sharedObject;
        });
    }
    

提交回复
热议问题