iOS

单例的写法

2018-08-15  本文已影响4人  说不出口的喵

单例模式的创建方式;

同步锁 :NSLock

@synchronized(self) {}

信号量控制并发:dispatch_semaphore_t

条件锁:NSConditionLock

dispatch_once_t

考虑数据和线程问题,苹果官方推荐开发者使用dispatch_once_t来创建单例,那么我就采用dispatch_once_t方法来创建一个单例,类名为OneTimeClass。

#import "Singleton.h"

@implementation Singleton

static Singleton* _instance = nil;

+(instancetype) shareInstance

{

    static dispatch_once_t onceToken ;

    dispatch_once(&onceToken, ^{

        _instance = [[super allocWithZone:NULL] init] ;

    }) ;

    return _instance ;

}

+(id) allocWithZone:(struct _NSZone *)zone

{

    return [Singleton shareInstance] ;

}

-(id) copyWithZone:(struct _NSZone *)zone

{

    return [Singleton shareInstance] ;

}

@end

===================以下的不太好的创建方式==============

static PPLAccountManager *sharedInstance = nil;

1.最简单(非线程安全)

+ (PPLAccountManager*)sharedManager {

    if (sharedInstance ==nil) {     

        sharedInstance = [[self alloc]init];  

    }    

    return sharedInstance;

 }

    单线程下运行正常,但是在多线程下就有问题了。如果两个线程同时运行到判断shareInstance是否为nil的if语句,且shareInstance没有创建时候,那么2个线程都会创建一个实例,此时单例就不在满足单例模式的要求了。为了保证多线程环境下我们还是只能得到类型的一个实例,需要加上一个同步锁。如下:

2.线程安全(不是最优)

+ (PPLAccountManager*)sharedManager {

    @synchronized(self){    

      if (sharedInstance == nil) {            

          sharedInstance = [[selfalloc]init];        

      }        

      return sharedInstance;

   }

 }

   这里还不是很完美。我们还是设想两个线程同时想创建一个实例,由于同一时刻只能有一个能得到同步锁,每当第一个线程锁加上锁,第二个线程只能等待,当第一个线程发现实例还没有创建时,它创建一个实例。接着第一个线程释放同步锁,此时第二个线程可以加上同步锁,并运行接下来的 代码。我们每次得到单例实例,都会试图加上一个线程锁,而加锁是一个非常耗时的操作,在没有必要的时候,我们尽量要避免。

3.线程安全(逻辑复杂)

+ (PPLAccountManager*)sharedManager {

   if (sharedInstance == nil) {      

        @synchronized(self){   

            if (sharedInstance == nil) {      

                sharedInstance = [[self alloc]init];          

            }   

        }   

   }

   return sharedInstance;

 }

  这里用了2个if判断来提高效率,但是代码实现逻辑比较复杂,容易出错,我们还有更加优秀的的解法。

上一篇下一篇

猜你喜欢

热点阅读