GCD dispatch_barrier 还是 dispatch_sync?

GCD dispatch_barrier or dispatch_sync?

我有一些关于 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 吗?如果是,这种方式在实际编程中流行吗?如果不是,请告诉我原因。非常感谢!

实际上,在此示例中,将 dispatch_barrier_async 替换为 dispatch_sync 会产生意外行为。您有并发队列来访问照片 - 这意味着,它可以让您 运行 同时进行多项操作。一次从任意多个地方读取 _photosArray 是可以的。但是坏事发生了,如果你试图改变它的内容,而有人正在阅读它。 dispatch_barrier_async 来了 - 它可以让您将 "seriality" 添加到并发队列。以这种方式分派的块将等待,直到所有其他操作停止、开始,并且在其执行期间没有人会在该队列上开始任何操作。

经典Readers-writers problem

如有不明之处,欢迎随时提问

更新 1

您不能在 photos 方法中使用 async 函数。 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 呼叫将同时 运行。

例如,您有 thread1thread2。他们持有相同的对象 object。在某些地方他们同时打电话

线程 1NSLog(@"%@", [object photos]); 线程 2 : NSArray *photos = [object photos];

此调用将并发执行(即在同一时间),但会同步执行 - 线程会冻结,直到它们获得照片。

但是,如果你做这样的事情

线程 2NSArray *photos = [object addPhoto:newPhoto]; 线程 1 : NSLog(@"%@", [object photos]);

您的 thread1 冻结,直到将照片添加到数组中。但是,thread2 不会等待,直到照片实际添加 - 它会继续执行。