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 一样的效果了,失去了栅栏的效果了。