OC中实现单例模式
最简单的写法,存在线程安全问题:
@implementation Singleton
+ (instancetype)shareInstance {
static Singleton *instance = nil;
if (! instance) {
instance = [[Singleton alloc] init];
}
return instance;
}
@end
存在的线程安全问题是,可能出现两条线程同时判断了instance==nil,然后实例了两个Singleton出来。
测试代码:
dispatch_queue_t queue = dispatch_queue_create("gcd_test_label", DISPATCH_QUEUE_CONCURRENT);
for (int i=0; i<10; i++) {
dispatch_async(queue, ^(void) {
Singleton *singleton = [Singleton shareInstance];
});
}
运行结果:
甚至出现了EXC_BAD_ACCESS中断。
以下介绍几种实现线程安全的单利模式。
使用dispatch_once
//Singleton.h
@interface Singleton: NSObject
+ (instancetype)shareInstance;
//封锁init方法
- (instancetype)init NS_UNAVAILABLE;
//封锁new方法
+ (instancetype)new NS_UNAVAILABLE;
//封锁alloc方法
+ (instancetype)alloc NS_UNAVAILABLE;
@end
//Singleton.m
@implementation Singleton
+ (instancetype)shareInstance {
static Singleton *instance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^(void) {
instance = [[super allocWithZone:nil] initInner];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [Singleton shareInstance];
}
- (instancetype)initInner
{
self = [super init];
if (self) {
NSLog(@"Singleton init.");
}
return self;
}
@end
dispatch_once 保证了在predicate相同的条件下,传入的block在程序生命期内只执行一次。