dispatch_once可以保證一段代碼只被執行一次,因此出現之後使用最多的場景就是實現單例。本文來模擬實現dispatch_once的功能。
直接上代碼
static NSMutableDictionary *lockMapping = nil;
void do_once(int *predicate, void(^block)()){
if(*predicate != -1){
NSLock *lock = nil;
@synchronized ([NSObject class]) {
NSLog(@"get lock");
if(lockMapping == nil){
lockMapping = [NSMutableDictionary dictionary];
}
NSString *key = [NSString stringWithFormat:@"%p", predicate];
if(![lockMapping objectForKey:key]){
[lockMapping setObject:[[NSLock alloc] init]
forKey:key];
}
lock = [lockMapping objectForKey:key];
}
[lock lock];
if(*predicate != -1){
block();
*predicate = -1;
}
[lock unlock];
}
}
原理很簡單,就不做過多解釋了。使用:
@interface Test : NSObject
+ (instancetype)shareInstance;
@end
@implementation Test
+ (instancetype)shareInstance{
static int token;
static Test *t = nil;
do_once(&token, ^{
t = [[Test alloc] init];
NSLog(@"execute once");
});
NSLog(@"execute every time");
return t;
}
@end
測試:
int main()
{
for(int i = 0; i < 100; i++){
dispatch_async(dispatch_queue_create(0, DISPATCH_QUEUE_CONCURRENT), ^{
[Test shareInstance];
});
}
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
return 0;
}