1. 程式人生 > >GCD 之執行緒死鎖

GCD 之執行緒死鎖

GCD 確實好用 ,很強大,相比NSOpretion 無法提供 取消任務的功能。

如此強大的工具用不好可能會出現執行緒死鎖。 如下程式碼:

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"=================4");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"=================5");
    });
    NSLog(@"=================6");
}

GCD Queue 分為三種:

1,The main queue  :主佇列,主執行緒就是在個佇列中。

2,Global queues : 全域性併發佇列。

3,使用者佇列:是用函式 dispatch_queue_create 建立的自定義佇列

dispatch_sync 和  dispatch_async 區別:

dispatch_async(queue,block)  async 非同步佇列,dispatch_async 函式會立即返回, block會在後臺非同步執行。

dispatch_sync(queue,block)   sync 同步佇列,dispatch_sync 函式不會立即返回,及阻塞當前執行緒,等待 block同步執行完成。

分析上面程式碼:

viewDidLoad 在主執行緒中, 及在
dispatch_get_main_queue() 中,執行到sync 時 向
dispatch_get_main_queue()插入 同步 threed1.

sync 會等到 後面block 執行完成才返回, sync 又再 dispatch_get_main_queue() 佇列中,
它是序列佇列,sync 是後加入的,前一個是主執行緒,
所以 sync 想執行 block 必須等待主執行緒執行完成,主執行緒等待 sync 返回,去執行後續內容。

造成死鎖,sync 等待mainThread 執行完成, mianThread 等待sync 函式返回。

下面例子:
- (void)viewDidLoad
{
    [super viewDidLoad];

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
    
    NSLog(@"=================1");
    
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"=================2");

    });
    NSLog(@"=================3");

    
});

}

程式會完成執行,為什麼不會出現死鎖。

首先: async 在主執行緒中  建立了一個非同步執行緒 加入  全域性併發佇列,async 不會等待block 執行完成,立即返回,

1,async 立即返回, viewDidLoad 執行完畢,及主執行緒執行完畢。 
2,同時,全域性併發佇列立即執行非同步 block , 列印 1, 當執行到 sync 它會等待 block 執行完成才返回, 及等待
dispatch_get_main_queue() 佇列中的 mianThread 執行完成, 然後才開始呼叫block 。

因為1 和 2 幾乎同時執行,因為2 在全域性併發佇列上, 2 中執行到sync 時 1 可能已經執行完成或 等了一會,mainThread 很快退出, 2 等已執行後續內容。

如果阻塞了主執行緒,2 中的sync 就無法執行啦,mainThread 永遠不會退出, sync 就永遠等待著,

- (void)viewDidLoad
{
    [super viewDidLoad];

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"=================1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"=================2");
    });
    NSLog(@"=================3"); 
});
    NSLog(@"==========阻塞主執行緒");
    while (1) {
    }
    NSLog(@"========2==阻塞主執行緒");

}

列印如下:

2014-11-30 17:56:22.296 Test[6108:379350] =================1

2014-11-30 17:56:22.296 Test[6108:379231] ==========阻塞主執行緒

永遠等著。。。。。

知道原理以後就會減少出錯啦。