Barrier主要用于在多个异步操作完成之后,统一的对非线程安全的对象进行更新操作
适合于大规模的I/O操作
当访问数据库或文件的时候,更新数据的时候不能和其他更新或者读取的操作在同一时间执行,我们也可以使用调度组,也可以用dispatch_barrier来解决。
这里我们在使用Barrier只能用并发队列。这里指定的并发队列应该是自己通过dispatch_queue_create函数创建的。
官方文档的介绍
为什么?因为如果你传的是一个串行队列或者全局并发队列,这个函数等同于dispatch_sync函数。
多线程去操作线程不安全的类会出现问题,就比如说你并行异步的去下载图片的时候,如果同时的去把这些图片添加到可变数组中的时候。这个时候会有线程不安全的问题,就比如说这个时候存在一个问题,如果多个线程去同时去添加图片进数组,只有一个能成功,所以就会出现问题。这个时候我们就可以用dispatch_barrier_sync来解决。大概是这样子的。
这样的话图片都是顺序添加进去的,这里就是把i当做是图片了
//并行队列异步下载图片
dispatch_queue_t queue =dispatch_queue_create("hh", DISPATCH_QUEUE_CONCURRENT);
NSMutableArray * arrayM= [NSMutableArray array];
int i;
for(i=0;i<100;i++)
{
dispatch_async(queue, ^{
//模拟下载图片
//等待之前队列中的任务执行完毕之后,再去执行Barrier中的任务
});
dispatch_barrier_sync(queue, ^{
//添加到可变数组中,
[arrayM addObject:@(i)];
});
}
输出就是顺序输出的
这里再介绍dispatch_barrier_sync和dispatch_barrier_async的区别
/**参数1:要将barrier添加到的队列
参数2:barrier要执行的block
*/
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);
它们的共同点就是,等待在它前面插入队列的任务先执行完,等待它们自己的任务执行完再执行后面的任务
不同点就在于dispatch_barrier_sync将自己的任务插入到队列的时候,需要等待自己的任务结束之后才会继续插入被写在它后面的任务,然后执行它们,dispatch_barrier_async是将自己的任务插入到队列之后,不会等待自己的任务结束,它会继续把后面的任务插入到队列,然后等待自己的任务结束后才执行后面任务。
就比如说如果我们不用等待自己的任务结束就把后面的任务插入到队列中,上面那个例子我们使用的是dispatch_barrier_asyncde 的话会出现这样的情况。