主隊列添加劑同步任務(wù)
原因:對于主隊列無論是同步異步都不會創(chuàng)建線程,而且主隊列中的任務(wù)只有在主線程空閑的時候才會執(zhí)行.如果是主隊列同步會造成互相等待而鎖死.主隊列同步任務(wù)等待主線程執(zhí)行,主線程之后的任務(wù)等待主隊列任務(wù)完成。
解決辦法:在主隊列外面套一層并發(fā)隊列的異步任務(wù).或者使用主隊列異步任務(wù)
問題代碼:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event
{
NSLog(@"START----START");
//情況1:主隊列同步任務(wù)-----鎖死
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"%@", [NSThreadcurrentThread]);
NSLog(@"鎖死了嗎?");
});
NSLog(@"deadBlock1--END");
NSLog(@"OVER------OVER");
}
運行結(jié)果:
在當前隊列的任務(wù)(無論同步異步)里面,添加當前隊列同步任務(wù),造成鎖死當前線程,該同步任務(wù)之后的任務(wù)不會執(zhí)行
原因:(官方文檔)Do not call the dispatch_sync function from a
task that is executing on the same queue that you pass to your function
call. Doing so will deadlock the queue. If you need to dispatch to the
current queue, do so asynchronously using the dispatch_async function.
說明:以上說法不完全正確,雖然在并發(fā)隊列/全局隊列的任務(wù)里面,添加當前并發(fā)隊列同步任務(wù)不會造成鎖死,但是蘋果官方不建議這樣做.
解決辦法:使用dispatch_async添加異步任務(wù)
問題代碼:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event
{
NSLog(@"START----START");
//會鎖死
dispatch_queue_tqueue=dispatch_queue_create("串行隊列",NULL);
//
dispatch_queue_t queue=dispatch_get_main_queue();
//不會鎖死,不建議使用
//dispatch_queue_t
queue=dispatch_queue_create("并發(fā)隊列",
DISPATCH_QUEUE_CONCURRENT);
//dispatch_queue_t
queue=dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
NSLog(@"%@", [NSThreadcurrentThread]);
//在這之后的任務(wù)不會執(zhí)行,因為會該同步任務(wù)會造成死鎖
dispatch_sync(queue, ^{
NSLog(@"鎖死了嗎?");
});
NSLog(@"沒有--沒有--沒有");
});
NSLog(@"deadBlock2--END");
NSLog(@"OVER------OVER");
}
運行結(jié)果
多個NSOperation之間循環(huán)依賴
原因:任務(wù)之間相互等待,造成死鎖
解決辦法:添加依賴的時候特別注意,不要有循環(huán)依賴
問題代碼
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event
{
//創(chuàng)建隊列
NSOperationQueue*queue=[NSOperationQueuenew];
NSBlockOperation*blockOp1=[NSBlockOperationblockOperationWithBlock:^{
[NSThreadsleepForTimeInterval:2];
NSLog(@"我是任務(wù)1--%@", [NSThreadcurrentThread]);
}];
NSBlockOperation*blockOp2=[NSBlockOperationblockOperationWithBlock:^{
[NSThreadsleepForTimeInterval:2];
NSLog(@"我是任務(wù)2--%@", [NSThreadcurrentThread]);
}];
NSBlockOperation*blockOp3=[NSBlockOperationblockOperationWithBlock:^{
[NSThreadsleepForTimeInterval:2];
NSLog(@"我是任務(wù)3--%@", [NSThreadcurrentThread]);
}];
NSBlockOperation*blockOp4=[NSBlockOperationblockOperationWithBlock:^{
NSLog(@"我是任務(wù)4--%@", [NSThreadcurrentThread]);
}];
//注意:千萬不要有循環(huán)依賴:即循環(huán)等待
[blockOp2addDependency:blockOp1];
[blockOp3addDependency:blockOp2];
[blockOp4addDependency:blockOp3];
//循環(huán)依賴,導致相互等待,相互鎖死,所有任務(wù)都不會執(zhí)行
[blockOp1addDependency:blockOp4];
[queueaddOperations:@[blockOp1,blockOp2,blockOp3,blockOp4]waitUntilFinished:NO];
NSLog(@"到這里了嗎");
}
運行結(jié)果
總結(jié)
使用dispatch_sync時候必須要慎重或者少用.如果要順序執(zhí)行可以用串行隊列異步任務(wù)代替
最好不要在當前隊列的任務(wù)里面,添加當前隊列同步任務(wù),會造成當前線程鎖死,導致之后的任務(wù)不會執(zhí)行.特別是當前線程是主線程的時候后果很嚴重.
stackoverflow相關(guān)討論:Posts containing 'dispatch_sync in dispatch_async' - Stack Overflow