1.共同點
dispatch_barrier_ 有阻塞隊列的意思。
在柵欄函數之前的先執行,在柵欄后面的后執行。
dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
//dispatch_get_global_queue(0, 0);
NSLog(@"pre 1");
dispatch_async(queue, ^{
NSLog(@"task 1");
});
NSLog(@"pre 2");
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
[NSThread sleepForTimeInterval:1];
NSLog(@"task 2");
});
NSLog(@"pre barrier");
dispatch_barrier_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"=========barrier==============");
});
NSLog(@"pre 3");
dispatch_async(queue, ^{
NSLog(@"task 3");
});
NSLog(@"pre 4");
dispatch_async(queue, ^{
NSLog(@"task 4");
});
結果大概是這樣的:
2020-06-24 17:10:51.732877+0800 Test[2978:214418] pre 1
2020-06-24 17:10:51.733031+0800 Test[2978:214418] pre 2
2020-06-24 17:10:51.733051+0800 Test[2978:214524] task 1
2020-06-24 17:10:51.733135+0800 Test[2978:214418] pre barrier
2020-06-24 17:10:51.733186+0800 Test[2978:214523] <NSThread: 0x600002dacf40>{number = 4, name = (null)}
2020-06-24 17:10:51.733233+0800 Test[2978:214418] pre 3
2020-06-24 17:10:51.733330+0800 Test[2978:214418] pre 4
2020-06-24 17:10:52.734736+0800 Test[2978:214523] task 2
2020-06-24 17:10:52.735266+0800 Test[2978:214523] <NSThread: 0x600002dacf40>{number = 4, name = (null)}
2020-06-24 17:10:52.735421+0800 Test[2978:214523] =========barrier==============
2020-06-24 17:10:52.735557+0800 Test[2978:214523] task 3
2020-06-24 17:10:52.735562+0800 Test[2978:214527] task 4
2.區別
dispatch_barrier_async不會阻塞當前線程,block添加到queue中后就會立即返回執行線程中后面的方法,如打印后面的pre 3,dispatch_barrier_sync會卡住當前線程,并且block是在當前線程中執行的,比如說主線程,pre3會在barrier block執行之后再執行。
把代碼中的dispatch_barrier_async替換成dispatch_barrier_sync執行得到的結果:
2020-06-24 17:40:34.357265+0800 Test[3111:231198] pre 1
2020-06-24 17:40:34.357412+0800 Test[3111:231198] pre 2
2020-06-24 17:40:34.357423+0800 Test[3111:231347] task 1
2020-06-24 17:40:34.357521+0800 Test[3111:231198] pre barrier
2020-06-24 17:40:34.357583+0800 Test[3111:231350] <NSThread: 0x600000e23f00>{number = 3, name = (null)}
2020-06-24 17:40:35.361841+0800 Test[3111:231350] task 2
2020-06-24 17:40:35.362108+0800 Test[3111:231198] <NSThread: 0x600000e64f40>{number = 1, name = main}
2020-06-24 17:40:35.362203+0800 Test[3111:231198] =========barrier==============
2020-06-24 17:40:35.362306+0800 Test[3111:231198] pre 3
2020-06-24 17:40:35.362413+0800 Test[3111:231198] pre 4
2020-06-24 17:40:35.362429+0800 Test[3111:231350] task 3
2020-06-24 17:40:35.362561+0800 Test[3111:231347] task 4
3.注意點
dispatch_barrier_async的官方Discussion:
Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked. When the barrier block reaches the front of a private concurrent queue, it is not executed immediately. Instead, the queue waits until its currently executing blocks finish executing. At that point, the barrier block executes by itself. Any blocks submitted after the barrier block are not executed until the barrier block completes.
The queue you specify should be a concurrent queue that you create yourself using the [`dispatch_queue_create`](apple-reference-documentation://hccjgwsoUD) 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_async`](apple-reference-documentation://hcVyOLxquW) function.
第一點說的dispatch_barrier_async的作用。
第二點需要注意的是queue的選擇,需要是自己創建的,dispatch_queue_create并且是concurrent的queue,不能是serial或者全局的global concurrent queues。
serial好理解,global concurrent queues這個確實不大理解,不過實驗過后確實不行。把之前的代碼里的代碼替換下,queue = dispatch_get_global_queue(0, 0)。
結果得到:
2020-06-24 17:30:24.390843+0800 Test[3058:224866] pre 1
2020-06-24 17:30:24.390967+0800 Test[3058:224866] pre 2
2020-06-24 17:30:24.390980+0800 Test[3058:225039] task 1
2020-06-24 17:30:24.391076+0800 Test[3058:224866] pre barrier
2020-06-24 17:30:24.391150+0800 Test[3058:225042] <NSThread: 0x6000039bc100>{number = 6, name = (null)}
2020-06-24 17:30:24.391199+0800 Test[3058:224866] pre 3
2020-06-24 17:30:24.391228+0800 Test[3058:225039] <NSThread: 0x6000039f3f00>{number = 5, name = (null)}
2020-06-24 17:30:24.391286+0800 Test[3058:224866] pre 4
2020-06-24 17:30:24.391306+0800 Test[3058:225043] task 3
2020-06-24 17:30:24.391342+0800 Test[3058:225039] =========barrier==============
2020-06-24 17:30:24.391591+0800 Test[3058:225041] task 4
2020-06-24 17:30:25.393049+0800 Test[3058:225042] task 2
注意看task2執行到barrier block后面。
dispatch_barrier_async 表現確實跟dispatch_async 一樣的效果了,失去了柵欄的效果了。