dispatch_barrier_sync 和dispatch_barrier_async的區別

需求:有4個任務{1,2,3,4},執行完前2個再執行後2個

這裏我們用到柵欄函數dispatch_barrier_(a)sync,(也可以用隊列組),我們要注意的是不能使用全局併發隊列(系統提供給我們的)否則會散失柵欄函數的意義

區別:先看官方文檔

dispatch_barrier_sync: Submits a barrier block object for execution and waits until that block completes.(提交一個柵欄函數在執行中,它會等待柵欄函數執行完)

dispatch_barrier_async: Submits a barrier block for asynchronous execution and returns immediately.(提交一個柵欄函數在異步執行中,它會立馬返回)

第一種解釋

作者理解:dispatch_barrier_sync 需要等待柵欄執行完纔會執行柵欄後面的任務,
而dispatch_barrier_async 無需等待柵欄執行完,會繼續往下走(保留在隊列裏)

原因:在同步柵欄時柵欄函數在主線程中執行,而異步柵欄中開闢了子線程柵欄函數在子線程中執行

1.先來看看dispatch_barrier_sync

- (void) barrier {
    NSLog(@"start");
    
    dispatch_queue_t myQueue = dispatch_queue_create("ff", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(myQueue, ^{
        NSLog(@"%@--1", [NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
           NSLog(@"%@--2", [NSThread currentThread]);
       });
    
    dispatch_barrier_sync(myQueue, ^{
        NSLog(@"+++barrier ++++++");
    });
    NSLog(@"++++++++++++barrier 之後");
    
    dispatch_async(myQueue, ^{
          NSLog(@"%@--3", [NSThread currentThread]);
      });
      dispatch_async(myQueue, ^{
             NSLog(@"%@--4", [NSThread currentThread]);
         });
    NSLog(@"last");
}

打印結果:

2020-06-20 08:31:08.892663+0800 OCTestFirst[6439:172483] start
2020-06-20 08:31:08.893001+0800 OCTestFirst[6439:172646] <NSThread: 0x600002a48440>{number = 6, name = (null)}--2
2020-06-20 08:31:08.893007+0800 OCTestFirst[6439:172648] <NSThread: 0x600002a4aa40>{number = 5, name = (null)}--1
2020-06-20 08:31:08.893166+0800 OCTestFirst[6439:172483] +++barrier ++++++
2020-06-20 08:31:08.893274+0800 OCTestFirst[6439:172483] ++++++++++++barrier 之後
2020-06-20 08:31:08.893375+0800 OCTestFirst[6439:172483] last
2020-06-20 08:31:08.893430+0800 OCTestFirst[6439:172646] <NSThread: 0x600002a48440>{number = 6, name = (null)}--4
2020-06-20 08:31:08.893488+0800 OCTestFirst[6439:172648] <NSThread: 0x600002a4aa40>{number = 5, name = (null)}--3

得到結果:柵欄函數確實分割了任務,但是任務執行的順序的確是無序的(異步函數)

2 換成dispatch_barrier_async

- (void) barrier {
    NSLog(@"start");
    
    dispatch_queue_t myQueue = dispatch_queue_create("ff", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(myQueue, ^{
        NSLog(@"%@--1", [NSThread currentThread]);
    });
    dispatch_async(myQueue, ^{
           NSLog(@"%@--2", [NSThread currentThread]);
       });
    
    dispatch_barrier_async(myQueue, ^{
        NSLog(@"+++barrier ++++++");
    });
    NSLog(@"++++++++++++barrier 之後");
    
    dispatch_async(myQueue, ^{
          NSLog(@"%@--3", [NSThread currentThread]);
      });
      dispatch_async(myQueue, ^{
             NSLog(@"%@--4", [NSThread currentThread]);
         });
    NSLog(@"last");
}

打印結果

2020-06-20 08:34:09.223552+0800 OCTestFirst[6485:174586] start
2020-06-20 08:34:09.223936+0800 OCTestFirst[6485:174586] ++++++++++++barrier 之後
2020-06-20 08:34:09.224071+0800 OCTestFirst[6485:174586] last
2020-06-20 08:34:09.225737+0800 OCTestFirst[6485:175133] <NSThread: 0x60000371bb00>{number = 10, name = (null)}--2
2020-06-20 08:34:09.225876+0800 OCTestFirst[6485:174911] <NSThread: 0x600003702440>{number = 8, name = (null)}--1
2020-06-20 08:34:09.226888+0800 OCTestFirst[6485:175133] +++barrier ++++++
2020-06-20 08:34:09.227540+0800 OCTestFirst[6485:175133] <NSThread: 0x60000371bb00>{number = 10, name = (null)}--3
2020-06-20 08:34:09.227540+0800 OCTestFirst[6485:174911] <NSThread: 0x600003702440>{number = 8, name = (null)}--4

特別注意:

The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_sync function.

官方說明大意:在使用柵欄函數時.使用自定義隊列纔有意義,如果用的是串行隊列或者系統提供的全局併發隊列,這個柵欄函數的作用等同於一個同步函數的作用

第二種解釋

在這裏插入圖片描述
barrier裏給了一個比較費時的操作便於看清楚

給的圖裏寫的是dispatch_barrier_sync,因爲我們需要先看看我們熟悉的等待——sync是什麼效果,直接跑起來
在這裏插入圖片描述
可以看到,確實是1、2、3號任務併發執行完了,然後再執行的我們的0號任務,再併發執行的4、5、6號任務,當然,point3和barrier之間是有明顯停頓的,截圖無法表現。對於這個輸出,應該是意料之中的。

接下來,代碼進行一點點修改,dispatch_barrier_sync改成dispatch_barrier_async。
在這裏插入圖片描述
區別很明顯,跟sync的情況相比,aaa、bbb的輸出位置完全不同,async的時候aaa的輸出在任務0結束之前,sync的aaa輸出在任務0結束之後

好了,說到這應該差不多能想通了,我們開始總結
dispatch_barrier_sync和dispatch_barrier_async的共同點:
1、都會等待在它前面插入隊列的任務(1、2、3)先執行完
2、都會等待他們自己的任務(0)執行完再執行後面的任務(4、5、6)
dispatch_barrier_sync和dispatch_barrier_async的不共同點:
在將任務插入到queue的時候,dispatch_barrier_sync需要等待自己的任務(0)結束之後纔會繼續程序,然後插入被寫在它後面的任務(4、5、6),然後執行後面的任務
而dispatch_barrier_async將自己的任務(0)插入到queue之後,不會等待自己的任務結束,它會繼續把後面的任務(4、5、6)插入到queue

原文鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章