我们经常在开发中使用单例来管理一些属性或者重复调用。但是我经常不了解为什么这样写,知其然,更要知其所以然。简单的一些理解

单例创建方式一

#import "DataManager.h"
static DataManager *defaultManager = nil;
@implementation DataManager
+ (DataManager*)sharedInstance{
@synchronized(self) {
if (defaultManager == nil) {
defaultManager = [[self alloc] init];
}
}
return defaultManager;
}
@end

关键字@synchronized

@synchronized,代表这个方法加锁, 相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程例如B正在用这个方法,有的话要等正在使用synchronized方法的线程B运行完这个方法后再运行此线程A,没有的话,直接运行。它包括两种用法:synchronized 方法和 synchronized 块。

@synchronized 方法控制对类(一般在iOS中用在单例中)的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法锁方能执行,否则所属就会发生线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类,至多只有一个处于可执行状态,从而有效避免了类成员变量的访问冲突(只要所有可能访问类的方法均被声明为 synchronized)
synchronized 块: @通过 synchronized关键字来声明synchronized 块。语法如下:
@synchronized(syncObject) { }

synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。      

 

单例创建方式二

#import "DataManager.h"
@implementation DataManager
+ (instancetype)sharedInstance{
static DataManager *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[DataManager alloc]init];
});
return instance;
}
@end

声明一个静态这是 dispatch_one_t,确保这些初始化代码只能被执行一次。

typedef long dispatch_once_t;其实是一个long类型

dispatch_once 不仅意味着代码仅会被运行一次,而且还是线程安全的,这就意味着你不需要使用诸如@synchronized之类的来防止使用多个线程或者队列时不同步的问题。

dispatch_once的作用正如其名:对于某个任务执行一次,且只执行一次。 dispatch_once函数有两个参数,第一个参数onceToken用来保证执行一次,第二个参数是要执行一次的任务block,使用 Grand Central Dispatch(GCD)执行一个 block 来初始化 DataManager 实例。