GCD 雖相比NSOpretion 無法提供 取消任務的功能,確因方便而強大廣受喜愛。
但是如此強大的工具用不好可能會出現(xiàn)線程死鎖。 如下代碼:
- (void)viewDidLoad
{
? ? [super viewDidLoad];
? ? NSLog(@"=================4");
? ? dispatch_sync(dispatch_get_main_queue(), ^{
? ? ? ? NSLog(@"=================5");
? ? });
? ? NSLog(@"=================6");
}
GCD Queue 分為三種:
1,The main queue? :主隊列,主線程就是在個隊列中。
2,Global queues : 全局并發(fā)隊列。
3,用戶隊列:是用函數(shù) dispatch_queue_create 創(chuàng)建的自定義隊列
dispatch_sync 和? dispatch_async 區(qū)別:
dispatch_async(queue,block)? async 異步執(zhí)行,dispatch_async 函數(shù)會立即返回, block會在后臺異步執(zhí)行。
dispatch_sync(queue,block)? sync 同步分發(fā),順序執(zhí)行,dispatch_sync 函數(shù)不會立即返回,插入到當前線程,等待 block同步執(zhí)行完成。
分析上面代碼:
viewDidLoad 在主線程中, 已在
dispatch_get_main_queue() 中,執(zhí)行到sync 時 向
dispatch_get_main_queue()插入 同步 threed1還是主線程.
sync 會等到 其block 執(zhí)行完成才返回并執(zhí)行后面的代碼, sync 又在 dispatch_get_main_queue() 隊列中的viewdidload中,在串形隊列中,sync 在上一個函數(shù)還沒執(zhí)行完時插入,形成在主線程有兩個互相等待執(zhí)行結束的情況,
sync 想執(zhí)行 block 必須等待主線程中的上一個任務didload執(zhí)行完成,而didload 必須等待 sync 執(zhí)行block返回才能去執(zhí)行后續(xù)代碼。
造成死鎖,sync 等待mainThread 執(zhí)行完成, mianThread 等待sync 函數(shù)返回。
下面例子:
- (void)viewDidLoad
{
? ? [super viewDidLoad];
? ? dispatch_async(dispatch_get_global_queue(0, 0), ^{
? ?
? ? NSLog(@"=================1");
? ?
? ? dispatch_sync(dispatch_get_main_queue(), ^{
? ? ? ? NSLog(@"=================2");
? ? });
? ? NSLog(@"=================3");
? ?
});
}
程序會完成執(zhí)行,為什么不會出現(xiàn)死鎖。
首先: async 在主線程中? 創(chuàng)建了一個異步線程 加入? 全局并發(fā)隊列,async 不會等待block 執(zhí)行完成,立即返回,
1,async 立即返回,并在子線程執(zhí)行其block 打印1,到碰到sync main判斷主線程在執(zhí)行任務,若有就等等,也可能是一直等。當viewDidLoad 順序執(zhí)行后續(xù)代碼并從主線程中清除,然后sync main block執(zhí)行。打印2,之后再打印3
2,同時,全局并發(fā)隊列立即執(zhí)行異步 block , 打印 1, 當執(zhí)行到 sync 它會等待 block 執(zhí)行完成才返回, 及等待
dispatch_get_main_queue() 隊列中的 mianThread 執(zhí)行完成, 然后才開始調(diào)用block 。
因為1 和 2 幾乎同時執(zhí)行,因為2 在全局并發(fā)隊列上, 2 中執(zhí)行到sync 時 1 可能已經(jīng)執(zhí)行完成或 等了一會。
如果阻塞了主線程,2 中的sync 就無法執(zhí)行啦,mainThread 永遠不會退出, sync 就永遠等待著,
- (void)viewDidLoad
{
? ? [super viewDidLoad];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
? ? NSLog(@"=================1");
? ? dispatch_sync(dispatch_get_main_queue(), ^{
? ? ? ? NSLog(@"=================2");
? ? });
? ? NSLog(@"=================3");
});
? ? NSLog(@"==========阻塞主線程");
? ? while (1) {
? ? }
? ? NSLog(@"========2==阻塞主線程");
}
打印如下:
2014-11-30 17:56:22.296 Test[6108:379350] =================1
2014-11-30 17:56:22.296 Test[6108:379231] ==========阻塞主線程。
簡單理解主線程,和任務的同/異步分發(fā)。