实际上,在这个例子中,替换dispatch_barrier_async
with dispatch_sync
会产生意想不到的行为。您有并发队列来访问照片 - 这意味着,它可以让您同时运行多个操作。读书没问题_photosArray
一次从任意多个地方出发。但是,如果您在有人阅读它的同时尝试更改其内容,就会发生不好的事情。来了dispatch_barrier_async
- 可以这么说,它可以让您将“串行性”添加到并发队列中。以这种方式分派的块将等待,直到所有其他操作停止、启动,并且在执行时没有人会在该队列上启动任何操作。
很经典读者-作者问题 https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem.
如果有什么无法解释的地方,请随时询问
Update 1
你不能使用async
功能于photos
方法。dispatch_sync
使您的方法等待任务执行。
我用数字标记了执行流程
- (NSArray *)photos
{
__block NSArray *array; //1. Here array is nil
dispatch_sync(self.concurrentPhotoQueue, ^{ //2. dispatch task and wait it ends execution
array = [NSArray arrayWithArray:_photosArray]; //3. Array filled with photos
});
return array; //4. Array filled with photos
}
如果你使用async
- (NSArray *)photos
{
__block NSArray *array; //1. Here array is nil
dispatch_async(self.concurrentPhotoQueue, ^{ //2. dispatch task and move on
array = [NSArray arrayWithArray:_photosArray]; //4. Array filled with photos
});
return array; //3. Array is still nil
}
Update 2
Several dispatch_sync
呼叫将同时运行。
例如,你有thread1 and thread2。他们持有同一个物体object。在某些地方他们同时打电话
thread1 : NSLog(@"%@", [object photos]);
thread2 : NSArray *photos = [object photos];
此调用将同时执行(即在同一时间),但同步执行 - 线程冻结直到获取照片。
但是,如果你做了这样的事情
thread2 : NSArray *photos = [object addPhoto:newPhoto];
thread1 : NSLog(@"%@", [object photos]);
your thread1冻结直到照片添加到数组中。但,thread2不会等待,直到照片实际添加 - 它只是继续执行。