我对dispatch_barrier
和dispatch_sync
有一些疑问。
这是代码:
- (void)addPhoto:(Photo *)photo
{
if (photo) { // 1
dispatch_barrier_async(self.concurrentPhotoQueue, ^{ // 2
[_photosArray addObject:photo]; // 3
dispatch_async(dispatch_get_main_queue(), ^{ // 4
[self postContentAddedNotification];
});
});
}
}
- (NSArray *)photos
{
__block NSArray *array; // 1
dispatch_sync(self.concurrentPhotoQueue, ^{ // 2
array = [NSArray arrayWithArray:_photosArray]; // 3
});
return array;
}
在addPhoto
方法中,它使用dispatch_barrier_async
。在photos
方法中,它使用dispatch_sync
。我可以将dispatch_barrier_async
替换为dispatch_sync
吗?如果是的话,这在实际编程中是否受欢迎?如果不是,请告诉我原因。非常感谢!
答案 0 :(得分:3)
实际上,在此示例中,将dispatch_barrier_async
替换为dispatch_sync
会产生意外行为。您有并发队列来访问照片 - 这意味着,它允许您同时运行多个操作。可以在一次中从多个地方阅读_photosArray
。但是如果你试图改变它的内容,那么就会发生不好的事情。这里有dispatch_barrier_async
- 它可以让你说,为并发队列添加“连续性”。以这种方式调度的块将等待,直到所有其他操作停止,启动,并且在执行时没有人将在该队列上不启动任何操作。
这是经典的Readers-writers problem。
如果有什么不明原因,请随时询问
更新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
}
更新2
多个dispatch_sync
次呼叫将同时运行。
例如,您有 thread1 和 thread2 。它们拥有相同的对象对象。在某些地方,他们同时打电话
thread1 :NSLog(@"%@", [object photos]);
thread2 :NSArray *photos = [object photos];
此调用将同时执行(即同时执行),但同步执行 - 线程冻结直到他们获得照片。
但是,如果你做这样的事情
thread2 :NSArray *photos = [object addPhoto:newPhoto];
thread1 :NSLog(@"%@", [object photos]);
你的 thread1 冻结,直到照片添加到数组中。但是, thread2 不会等待,直到照片实际添加 - 它才会继续执行。