1. 程式人生 > >ios多執行緒死鎖解析

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,^{  //設此blockA,則A被新增到queue

if(queue != mainQueue)

  {

建立新執行緒,執行所有下面的程式碼

 }else{

不會建立新執行緒,直接執行所有下面的程式碼

}

            //紅色為系統預設操作,程式碼裡沒有的

            if(queue == 序列佇列)

  {  

     //是序列佇列,才上鎖

lock(queue.lock);//成功上鎖

            }

            NSLog(@”%@---1”,[NSThreadcurrentThread]);

            Dispatch_sync(queue,^{ //設此blockB,則B被新增到queue

            //紅色為系統預設操作,程式碼裡沒有的

            if(queue == 序列佇列)

          {  

             lock(queue.lock);//B不能上鎖,因為A已經Lock,而且A還沒unlock

            //由此造成死鎖:B此時會等待A unlock但是Aunlock必須等B執行

完才會呼叫,所以永遠B都會在等待AA又在等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);

}

});