在隊列中,柵欄塊必須單獨執行,不能與其它塊并行。這只對并發隊列有意義,因為串行隊列中的塊總是按順序逐個來執行的。并發隊列中如果發現接下來要處理的塊是個柵欄塊(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);
就可以實現 讀寫的同步了。
書上的代碼 也不可全信,只有自己試了了才知道。畢竟,盡信書,不如無書!