同步串行
先看一個頭條的面試真題,下面這段代碼有什么問題?
-(void)viewDidLoad
{
dispatch_sync(dispatch_get_main_queue(), ^{
[self doSomething];
});
}
這是一個同步串行的問題,這段代碼會造成程序死鎖,下面分析一下為什么會造成程序死鎖
上圖中叠艳,首先向主隊列中提交了一個 viewDidLoad 的任務撞羽,后續(xù)又提交了一個 Block 任務 蝙斜。 現(xiàn)在分派 viewDidLoad 到主線程中去執(zhí)行简软,在它執(zhí)行過程中需要調(diào)用 Block 射众,等 Block 同步調(diào)用完成之后正压,這個 viewDidLoad 才能繼續(xù)向下走,所以 viewDidLoad 的調(diào)用結(jié)束依賴于 Block 方法執(zhí)行完责球。
而隊列是遵循先進先出(FIFO)原則的,Block 要想執(zhí)行拓劝,就必須等待 viewDidLoad 調(diào)用完成雏逾。 由此就產(chǎn)生了隊列的循環(huán)等待,造成死鎖.
再來看一段代碼,有沒有什么問題郑临?
-(void)viewDidLoad
{
dispatch_sync(serialQueue, ^{
//serialQueue是自定義的串行隊列
[self doSomething];
});
}
這段代碼可以正常運行,分析一下
viewDidLoad 在主隊列中栖博,提交到主線程處理,在 viewDidLoad方法運行到某一時刻的時候,會提交一個任務到串行隊列上厢洞。
串行隊列同步提交一個 Block 任務仇让,因為是同步的(同步提交就是在當前線程執(zhí)行),所以串行隊列中的任務也是提交到主線程中執(zhí)行,當串行隊列這個任務在主線程處理完成之后躺翻,再繼續(xù)處理 viewDidLoad 后續(xù)的代碼邏輯.
同步并發(fā)
看一段代碼 ,輸出什么?(美團新零售事業(yè)部的一個真題)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"1");
dispatch_queue_t globaQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(globaQueue, ^{
NSLog(@"2");
dispatch_sync(globaQueue, ^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
輸出日志 12345
因為是同步丧叽,所以都是在主線程執(zhí)行。globaQueue 是并發(fā)隊列公你,所以不會造成死鎖踊淳。如果將 倆個globaQueue 都換成串行隊列,就會造成死鎖.
異步串行
-(void)viewDidLoad
{
dispatch_async(dispatch_get_main_queue(), ^{
[self doSomething];
});
}
異步并發(fā)
繼續(xù)看下面這段代碼, 來自鵝廠的一個面試題
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1");
dispatch_queue_t globaQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globaQueue, ^{
[self performSelector:@selector(printLog) withObject:nil afterDelay:0];
});
NSLog(@"3");
}
-(void)printLog{NSLog(@"2");}
輸出結(jié)果是 1 3 陕靠, 2是不會打印的迂尝,分析
首先這是一個異步方式分配到全局并發(fā)隊列當中的脱茉,這個 Block 會在 GCD 底層的線程池當中的某一個線程中執(zhí)行。
GCD 底層所分派的這些線程默認是不開啟 Runloop 的垄开,而 performSelector 方法是需要創(chuàng)建相應的任務提交到 Runloop 上琴许,所以在 GCD 底層線程沒有 Runloop 的情況下,這個方法就會失效 .也就是說 performSelector 要想能夠有效執(zhí)行必須是它方法調(diào)用所屬的當前線程有 Runloop 的溉躲。
dispatch_barrier_async()
怎樣利用 GCD 實現(xiàn)多讀單寫 ? (滴滴美團面試真題)
Demo
dispatch_group_async()
使用 GCD 實現(xiàn)這個需求 : A B C 三個任務并發(fā) 榜田, 完成后執(zhí)行任務 D ? (愛奇藝面試真題)
Demo
NSOperation
- 添加任務依賴
- 任務執(zhí)行狀態(tài)控制
- 最大并發(fā)量
任務執(zhí)行狀態(tài)控制
可以控制 NSOperation 的哪些狀態(tài)? (DD面試真題)
- isReady
- isExecuting
- isFinished
- isCancelled
如果只重寫了 main 方法,底層控制變更任務執(zhí)行完成狀態(tài)签财,以及任務退出
如果只重寫了 start 方法 串慰, 自行控制任務狀態(tài)
系統(tǒng)是怎樣移除一個 isFinished = YES 的NSOperation的?
通過 KVO (KVO的實現(xiàn)機制參考 OC 語言特性篇)