ios多執行緒死鎖解析
問題:ios 誰能分析下多執行緒死鎖問題,感謝,分析圖一二為什麼是這個結果?
(問題帖子連結:http://zhidao.baidu.com/link?url=Lr9sNchrdnCLJdoc73WeHfL3lcu7lBvyKQ2hBrF2jbyM3wkJWeK0esMKOhIVL9wDfwOduh7pK3UCIwxreRBZjeyv0uYZpnCxR7dms05Ih4K)
網路看到一個帖子(連結如上)關於多執行緒死鎖問題,我挺感興趣,由此對這個問題做了回答,我參考了帖子中的答案
我的回答:
我採用分解法(把一個問題分解為多個問題),為什麼多執行緒會發送死鎖,由此我提出如下問題:
1, 序列queue 與並行queue的各自特點?
2, queue與執行緒什麼關係?
3, dispatch_sync() 與dispatch_async()函式實現?(後面有我自己的猜想實現)
答:
1:
1) 序列queue 和 並行queue本質都是一個連結串列(或是陣列),就用來存放任務(block)。
2)序列queue有鎖,並行queue沒有鎖
2:
序列queue:
1)執行緒會按新增任務的順序依次取出序列queue中的任務(block),然後執行,只有執行完一個任務,才能執行下一個任務。
2)執行緒在執行任務之前會上鎖,執行完任務後會解鎖
並行queue:
1)執行緒取出並行queue中任務,並且會建立新執行緒來執行任務。
2)執行緒執行任務的時候不會上鎖、解鎖,就直接執行任務
3:dispatch_sync和dispatch_async的虛擬碼實現
dispatch_sync(queue,block)
{
// 鎖
if(queue == 序列佇列)
{
//是序列佇列,才上鎖
lock(queue.lock);//每個序列queue都擁有自己唯一的鎖lock
}
//呼叫block
block();
//解鎖
if(queue == 序列佇列)
{
//是序列佇列,才解鎖
unlock(queue.lock)
}
}
dispatch_async(queue,block)
{
if(queue != mainQueue)
{
建立新執行緒,執行所有下面的程式碼
}else{
不會建立新執行緒,直接執行所有下面的程式碼
}
// 鎖
if(queue == 序列佇列)
{
//是序列佇列,才上鎖
lock(queue.lock);//每個序列queue都擁有自己唯一的鎖lock
}
//注意:dispatch_async比dispatch_sync多瞭如下操作
if(queue == 並行佇列)
{
//是並行佇列,建立新執行緒
dispatch_thread_t newThread = create_thread();
// 在新執行緒中執行任務(block)
newThread.run(
//呼叫block
block();
);
}else{ //不是並行佇列
//呼叫block
block();
}
//解鎖
if(queue == 序列佇列)
{
//是序列佇列,才解鎖
unlock(queue.lock)
}
}
知道以上情況,那我們就拿第一個例子解釋:如下圖
答案解析:
//新建了一個序列佇列並標識為”queue”
dispatch_queue_t queue = dispatch_queue_create(“queue”,DISPATCH_QUEUE_SERIAL);
dispatch_aysnc(queue,^{ //設此block為A,則A被新增到queue
if(queue != mainQueue)
{
建立新執行緒,執行所有下面的程式碼
}else{
不會建立新執行緒,直接執行所有下面的程式碼
}
//紅色為系統預設操作,程式碼裡沒有的
if(queue == 序列佇列)
{
//是序列佇列,才上鎖
lock(queue.lock);//成功上鎖
}
NSLog(@”%@---1”,[NSThreadcurrentThread]);
Dispatch_sync(queue,^{ //設此block為B,則B被新增到queue
//紅色為系統預設操作,程式碼裡沒有的
if(queue == 序列佇列)
{
lock(queue.lock);//B不能上鎖,因為A已經Lock,而且A還沒unlock
//由此造成死鎖:B此時會等待A unlock但是A的unlock必須等B執行
完才會呼叫,所以永遠B都會在等待A,A又在等B執行完……..
// 這裡有個重點:queue.lock每個queue有自己唯一的lock
所以只有同一個queue的任務(block)才會造成死鎖,因為lock()的引數,如果是不同的鎖,肯定是可以上鎖成功的,你懂了嗎?
}
NSLog(@”%@---2”,[NSThreadcurrentThread]);
//紅色為系統預設操作,程式碼裡沒有的
if(queue == 序列佇列)
{
unlock(queue.lock);//
}
});
dispatch_async(queue,^{
NSLog(@”%@---3”,[NSThreadcurrentThread]);
});
// 紅色為系統預設操作,程式碼裡沒有的
if(queue == 序列佇列)
{
unLock(queue.lock);
}
});