死鎖就是隊列引發的循環等待異步
一、一個比較常見的死鎖例子:主隊列同步async
- (void)viewDidLoad { [super viewDidLoad]; dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"deallock"); }); // Do any additional setup after loading the view, typically from a nib. }
在主線程中運用主隊列同步,也就是把任務放到了主線程的隊列中。
同步對於任務是馬上執行的,那麼當把任務放進主隊列時,它就會立馬執行,只有執行完這個任務,viewDidLoad纔會繼續向下執行。
而viewDidLoad和任務都是在主隊列上的,因爲隊列的先進先出原則,任務又需等待viewDidLoad執行完畢後才能繼續執行,viewDidLoad和這個任務就造成了相互循環等待,就形成了死鎖。
想避免這種死鎖,能夠將同步改爲異步dispatch_async,或者將dispatch_get_main_queue換成其餘串行或並行隊列,均可以解決。函數
二、一樣,下邊的代碼也會形成死鎖:spa
dispatch_queue_t serialQueue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL); dispatch_async(serialQueue, ^{ dispatch_sync(serialQueue, ^{ NSLog(@"deadlock"); }); });
外面的函數不管是同步仍是異步都會形成死鎖。
這是由於裏面的任務和外面的任務都在同一個serialQueue隊列內,又是同步,這就和上邊主隊列同步的例子同樣形成了死鎖
解決方法也和上邊同樣,將裏面的同步改爲異步dispatch_async,或者將serialQueue換成其餘串行或並行隊列,均可以解決線程
dispatch_queue_t serialQueue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL); dispatch_queue_t serialQueue2 = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL); dispatch_async(serialQueue, ^{ dispatch_sync(serialQueue2, ^{ NSLog(@"deadlock"); }); });
這樣是不會死鎖的,而且serialQueue和serialQueue2是在同一個線程中的。code