-
產(chǎn)生死鎖的四個(gè)必要條件
互斥條件:進(jìn)程對所分配到的資源不允許其他進(jìn)程進(jìn)行訪問,若其他進(jìn)程訪問該資源缘琅,只能等待粘都,直至占有該資源的進(jìn)程使用完成后釋放該資源
請求和保持條件:進(jìn)程獲得一定的資源之后,又對其他資源發(fā)出請求刷袍,但是該資源可能被其他進(jìn)程占有翩隧,此時(shí)請求阻塞,但又對自己獲得的資源保持不放
不可剝奪條件:是指進(jìn)程已獲得的資源呻纹,在未完成使用之前堆生,不可被剝奪,只能在使用完后自己釋放
環(huán)路等待條件:是指進(jìn)程發(fā)生死鎖后雷酪,必然存在一個(gè)進(jìn)程--資源之間的環(huán)形鏈
-
GCD線程死鎖產(chǎn)生的具體原因:在一個(gè)串行隊(duì)列的任務(wù)中淑仆,再向這個(gè)隊(duì)列同步添加任務(wù)。
典型例子:
我們分析一下:
主隊(duì)列main_queue是一個(gè)串行隊(duì)列哥力,串行隊(duì)列的特點(diǎn)就是隊(duì)列中所有任務(wù)必須順序執(zhí)行蔗怠。也就是說必須按照添加到隊(duì)列中的先后順序執(zhí)行。
我們再看一張圖:
我們在代碼中使用
dispatch_sync()
函數(shù)給主隊(duì)列添加了一個(gè)同步任務(wù):
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"線程死鎖");
});
}
也就是說后添加的同步任務(wù)5是在
viewDidLoad
任務(wù)2之后吩跋,只有等待任務(wù)2執(zhí)行完之后才能執(zhí)行任務(wù)5蟀淮,這就是串行隊(duì)列的特點(diǎn)。但是任務(wù)5是一個(gè)同步任務(wù)钞澳,必須等任務(wù)5執(zhí)行完才能執(zhí)行其它任務(wù),因此造成互相等待的死鎖涨缚。
再看一個(gè)例子
我們知道GCD分為同步任務(wù)和異步任務(wù)轧粟,最開始的例子是主線程的主隊(duì)列策治,相當(dāng)于是一個(gè)同步任務(wù)。而這個(gè)例子證明了兰吟,即便是在異步任務(wù)只要任務(wù)隊(duì)列是串行隊(duì)列通惫,在串行隊(duì)列的任務(wù)中再向隊(duì)列添加同步任務(wù),就會(huì)造成死鎖混蔼,關(guān)鍵點(diǎn)不是同步還是異步履腋,而是串行隊(duì)列。
總結(jié)
dispatch_sync()
函數(shù)會(huì)阻塞線程惭嚣。當(dāng)前隊(duì)列是串行隊(duì)列遵湖,任務(wù)必須順序執(zhí)行。在串行隊(duì)列的任務(wù)A中給這個(gè)隊(duì)列添加同步任務(wù)B晚吞,相當(dāng)于說這個(gè)串行隊(duì)列又多了一個(gè)任務(wù)B延旧,任務(wù)B如果想要執(zhí)行必須等待任務(wù)A執(zhí)行完,但是任務(wù)B是同步任務(wù)槽地,必須等任務(wù)B執(zhí)行完才能執(zhí)行其它任務(wù)迁沫,所以任務(wù)AB互相等待,造成死鎖捌蚊。