1、栅栏函数使用场景
异步执行两组操作,且第一组操作(多个任务)执行完成后,才开始执行第二组操作(多个任务)。
2、代码
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.concurrent", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"currentThread - %@",[NSThread currentThread]); // 打印当前线程
// 异步任务
dispatch_async(queueConcurrent, ^{
sleep(4);
NSLog(@"1 - %@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(3);
NSLog(@"2 - %@",[NSThread currentThread]);
});
//栅栏函数
dispatch_barrier_async(queueConcurrent, ^{
sleep(2);
NSLog(@"barrier - %@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(2);
NSLog(@"3 - %@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(1);
NSLog(@"4 - %@",[NSThread currentThread]);
});
2020-11-06 20:51:10.092033+0800 Demo[30480:2211900] currentThread - <NSThread: 0x600002150500>{number = 1, name = main}
2020-11-06 20:51:13.097126+0800 Demo[30480:2212114] 2 - <NSThread: 0x60000216ce00>{number = 6, name = (null)}
2020-11-06 20:51:14.095570+0800 Demo[30480:2212115] 1 - <NSThread: 0x600002167400>{number = 4, name = (null)}
2020-11-06 20:51:16.098314+0800 Demo[30480:2212115] barrier - <NSThread: 0x600002167400>{number = 4, name = (null)}
2020-11-06 20:51:17.102508+0800 Demo[30480:2212114] 4 - <NSThread: 0x60000216ce00>{number = 6, name = (null)}
2020-11-06 20:51:18.103299+0800 Demo[30480:2212115] 3 - <NSThread: 0x600002167400>{number = 4, name = (null)}
3、dispatch_barrier_async和dispatch_barrier_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_queue_t queueConcurrent = dispatch_queue_create("com.concurrent", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"currentThread - %@",[NSThread currentThread]); // 打印当前线程
// 异步任务
dispatch_async(queueConcurrent, ^{
sleep(4);
NSLog(@"1 - %@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(3);
NSLog(@"2 - %@",[NSThread currentThread]);
});
//栅栏函数
dispatch_barrier_async(queueConcurrent, ^{
sleep(2);
NSLog(@"barrier - %@",[NSThread currentThread]);
});
NSLog(@"判断区别");
dispatch_async(queueConcurrent, ^{
sleep(2);
NSLog(@"3 - %@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(1);
NSLog(@"4 - %@",[NSThread currentThread]);
});
2020-11-06 20:56:36.682431+0800 Demo[30728:2217328] currentThread - <NSThread: 0x600003944580>{number = 1, name = main}
2020-11-06 20:56:36.682687+0800 Demo[30728:2217328] 判断区别
2020-11-06 20:56:39.688071+0800 Demo[30728:2217409] 2 - <NSThread: 0x600003902540>{number = 5, name = (null)}
2020-11-06 20:56:40.686471+0800 Demo[30728:2217412] 1 - <NSThread: 0x600003909480>{number = 6, name = (null)}
2020-11-06 20:56:42.691081+0800 Demo[30728:2217412] barrier - <NSThread: 0x600003909480>{number = 6, name = (null)}
2020-11-06 20:56:43.693779+0800 Demo[30728:2217409] 4 - <NSThread: 0x600003902540>{number = 5, name = (null)}
2020-11-06 20:56:44.692659+0800 Demo[30728:2217412] 3 - <NSThread: 0x600003909480>{number = 6, name = (null)}
dispatch_queue_t queueConcurrent = dispatch_queue_create("com.concurrent", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"currentThread - %@",[NSThread currentThread]); // 打印当前线程
// 异步任务
dispatch_async(queueConcurrent, ^{
sleep(4);
NSLog(@"1 - %@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(3);
NSLog(@"2 - %@",[NSThread currentThread]);
});
//栅栏函数
dispatch_barrier_sync(queueConcurrent, ^{
sleep(2);
NSLog(@"barrier - %@",[NSThread currentThread]);
});
NSLog(@"判断区别");
dispatch_async(queueConcurrent, ^{
sleep(2);
NSLog(@"3 - %@",[NSThread currentThread]);
});
dispatch_async(queueConcurrent, ^{
sleep(1);
NSLog(@"4 - %@",[NSThread currentThread]);
});
2020-11-06 20:57:33.124990+0800 Demo[30788:2218815] currentThread - <NSThread: 0x6000019101c0>{number = 1, name = main}
2020-11-06 20:57:36.125472+0800 Demo[30788:2218907] 2 - <NSThread: 0x60000195d8c0>{number = 7, name = (null)}
2020-11-06 20:57:37.130359+0800 Demo[30788:2218908] 1 - <NSThread: 0x60000191e980>{number = 3, name = (null)}
2020-11-06 20:57:39.131764+0800 Demo[30788:2218815] barrier - <NSThread: 0x6000019101c0>{number = 1, name = main}
2020-11-06 20:57:39.132150+0800 Demo[30788:2218815] 判断区别
2020-11-06 20:57:40.133453+0800 Demo[30788:2218911] 4 - <NSThread: 0x60000192ce00>{number = 4, name = (null)}
2020-11-06 20:57:41.132689+0800 Demo[30788:2218908] 3 - <NSThread: 0x60000191e980>{number = 3, name = (null)}
理解:
dispatch_barrier_sync 阻塞当前线程,需要等待栅栏任务执行完,才会执行栅栏后面的任务。
dispatch_barrier_async 不阻塞当前线程,无需等待栅栏任务执行完,会继续往下走(任务保留在队列里)
原因:
同步栅栏时栅栏函数在主线程中执行。
异步栅栏中开辟子线程,栅栏函数在子线程中执行。
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.
在使用栅栏函数时,使用自定义队列才有意义。如果用的是串行队列或者系统提供的全局并发队列,这个栅栏函数的作用等同于一个同步函数的作用。
所以,必须自己使用dispatch_queue_create创建并行队列。如果你使用了串行队列或者全局队列,dispatch_barrier_async相当于dispatch_async,而dispatch_barrier_sync相当于dispatch_sync。
全局并发队列栅栏函数失效原因:
全局并发队列是系统创建,源码是宏定义数组。会在全局并发队列中处理它自有任务。使用栅栏函数阻塞全局并发队列无效。
网友评论