前言
dispatch_barrier_async 和 dispatch_group 是GDC中比较高级的用法,其作用都可以视为 等一段并发的工作完成后,接着处理某些其他事情。但二者还是有很大区别的,dipatch_barrier_async是对同一个队列的各个任务而设置一个节点的;而dispatch_group除此之外还可以对不同队列来统一设置一个节点(因此更强大)。
dispatch_barrier_async
一个dispatch barrier 允许在一个并发队列中创建一个同步点。当在并发队列中遇到一个barrier, 他会延迟执行barrier的block,等待所有在barrier之前提交的blocks执行结束。 这时,barrier block自己开始执行。 之后, 队列继续正常的执行操作。这里指定的并发队列应该是自己通过dispatch_queue_create函数创建的。如果你传的是一个串行队列或者全局并发队列,这个函数等同于dispatch_async函数。
所有在barrier block之后提交的blocks会等到barrier block结束之后才执行。
dispatch_barrier_async函数的作用
- 实现高效率的数据库访问和文件访问 (同步)
- 避免数据竞争 (特定到某点之后来单独处理)
例如: 在访问数据操作时,可以并行读取,因此这种操作应该放到concurrent Dispatch Queue中; 在读取完成后再统一进行其他处理操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| - (void)barrierTest { dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"----read table1-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----read table2-----%@", [NSThread currentThread]); }); dispatch_barrier_async(queue, ^{ NSLog(@"----barrier-- do something use both table1 and table2 -----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----do something after data operated in barrier -----%@", [NSThread currentThread]); }); }
|
输出结果:
1 2 3 4
| HuntTest[19408:3288590] ----read table2-----<NSThread: 0x6100002605c0>{number = 4, name = (null)} HuntTest[19408:3288588] ----read table1-----<NSThread: 0x600000260fc0>{number = 3, name = (null)} HuntTest[19408:3288588] ----barrier-- do something use both table1 and table2 -----<NSThread: 0x600000260fc0>{number = 3, name = (null)} HuntTest[19408:3288588] ----do something after data operated in barrier -----<NSThread: 0x600000260fc0>{number = 3, name = (null)}
|
dispatch_group
队列组(dispatch_group)可以将很多队列添加到一个组里,这样做的好处是,当这个组里所有的任务都执行完了,队列组会通过一个方法通知我们。这是一个很实用的功能。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| - (void)groupTest { dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(group, queue, ^{ for (NSInteger i = 0; i < 1; i++) { NSLog(@"group-01 - %@", [NSThread currentThread]); } }); dispatch_group_async(group, dispatch_get_main_queue(), ^{ for (NSInteger i = 0; i < 2; i++) { NSLog(@"group-02 - %@", [NSThread currentThread]); } }); dispatch_group_async(group, queue, ^{ for (NSInteger i = 0; i < 2; i++) { NSLog(@"group-03 - %@", [NSThread currentThread]); } }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"完成 - %@", [NSThread currentThread]); }); }
|
结果:
1 2 3 4 5 6
| HuntTest[19661:3299108] group-01 - <NSThread: 0x61000006eb40>{number = 3, name = (null)} HuntTest[19661:3299109] group-03 - <NSThread: 0x60800006ff00>{number = 4, name = (null)} HuntTest[19661:3299109] group-03 - <NSThread: 0x60800006ff00>{number = 4, name = (null)} HuntTest[19661:3298914] group-02 - <NSThread: 0x608000067fc0>{number = 1, name = main} HuntTest[19661:3298914] group-02 - <NSThread: 0x608000067fc0>{number = 1, name = main} HuntTest[19661:3298914] 完成 - <NSThread: 0x608000067fc0>{number = 1, name = main}
|
dispatch_group还提供了多个block之间的同步机制。
应用场景 在很多UGC(User Generated Content)产品中(如微博、赤兔、朋友圈),发一条图文并茂的动态总是群众喜闻乐见的。一个动态中可能包含多张图片,而且包含一个文字内容,因此我们可以将处理的block放到一个dispatch_group中。所有block都执行完成后,dispatch_group_notify再通知用户状态发送成功。即:
1 2 3 4 5 6 7 8 9 10 11 12
| NSMutableArray *imageURLs= [NSMutableArray array]; dispatch_group_t group = dispatch_group_create(); for (UIImage *image in images) { dispatch_group_enter(group); sendPhoto(image, success:^(NSString *url) { [imageURLs addObject:url]; dispatch_group_leave(group); }); } dispatch_group_notify(group, dispatch_get_global_queue(), ^{ postFeed(imageURLs, text); });
|
具体可参考: http://www.jianshu.com/p/4769680b983d
参考