需求:有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