先來(lái)段代碼:
+ (instancetype)shareInstance{
static BETestSingleton * single;
static dispatch_once_t onceToken;
NSLog(@"====>%ld",onceToken);
dispatch_once(&onceToken, ^{
NSLog(@"====>block內(nèi):%ld",onceToken);
single = [[BETestSingleton alloc] init];
});
NSLog(@"======>block外:%ld",onceToken);
return single;
}
這是利用dispatch_once實(shí)現(xiàn)單例的方式,運(yùn)行看看會(huì)輸出什么:
====>0
====>block內(nèi):768
======>block外:-1
生成完單例對(duì)象后,在其他地方調(diào)用單例:
NSString *testStr = [BETestSingleton shareInstance].testString;
會(huì)輸出:
====>-1
======>block外:-1
下面來(lái)看一下為什么這么輸出以及dispatch_once
的原理:
dispatch_once
主要是根據(jù)onceToken
的值來(lái)決定怎么去執(zhí)行代碼。
1.當(dāng)onceToken= 0
時(shí),線程執(zhí)行dispatch_once
的block中代碼
2.當(dāng)onceToken= -1
時(shí),線程跳過(guò)dispatch_once
的block中代碼不執(zhí)行
3.當(dāng)onceToken
為其他值時(shí),線程被阻塞,等待onceToken值改變
當(dāng)線程調(diào)用shareInstance
,此時(shí)onceToken= 0,調(diào)用block中的代碼,此時(shí)onceToken的值變?yōu)?68。當(dāng)其他線程再調(diào)用shareInstance
方法時(shí),onceToken的值已經(jīng)是768了,線程阻塞。當(dāng)block線程執(zhí)行完block之后,onceToken變?yōu)?1.其他線程不再阻塞,跳過(guò)block。下次再調(diào)用shareInstance
時(shí),block已經(jīng)為-1.直接跳過(guò)block。