在队列中,栅栏块必须单独执行,不能与其它块并行。这只对并发队列有意义,因为串行队列中的块总是按顺序逐个来执行的。并发队列中如果发现接下来要处理的块是个栅栏块(barrier block),那么就一直等到当前所有并发块都执行完毕,才会单独执行这个栅栏块。
这是Effective Objective-C 2.0 这本书 中对dispatch_barrier_async的说明,书中有一段示例代码,大概是这样的:
- (instancetype)init
{
self = [super init];
if (!self) {
return nil;
}
_concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
return self;
}
- (NSString *)name
{
__block NSString *name;
dispatch_sync(_concurrentQueue, ^{
name = _name;
});
return name;
}
- (void)setName:(NSString *)name
{
dispatch_barrier_async(_concurrentQueue, ^{
_name = name;
});
}
问题来了,以上代码能实现对name属性的读写同步吗?
按道理,是可以的。但事实并不可以,因为在这里苹果给我们挖了一个坑。。。
原因就是 在这里 我们使用的是全局并发队列。。
都是 并发队列 凭啥就不一样呢??
在这里,还真不一样,苹果在文档里说明如下:
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 queueor one of the global concurrent queues, this function behaves like the dispatch_async function.
点击查看原文
就是说,栅栏块应该在自己创建的并行队列里执行,如果是在串行队列或是全局并行队列中执行,那么就起不到栅栏的作用,和dispatch_async 函数效果一样了。
所以上面代码只要把_concurrentQueue 改成自己创建的
_concurrentQueue = dispatch_queue_create("com.people.test", DISPATCH_QUEUE_CONCURRENT);
就可以实现 读写的同步了。
书上的代码 也不可全信,只有自己试了了才知道。毕竟,尽信书,不如无书!