GCD dispatch_barrier还是dispatch_sync?

时间:2015-09-18 08:22:18

标签: grand-central-dispatch

我对dispatch_barrierdispatch_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吗?如果是的话,这在实际编程中是否受欢迎?如果不是,请告诉我原因。非常感谢!

1 个答案:

答案 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 不会等待,直到照片实际添加 - 它才会继续执行。