GCD dispatch_barrier or dispatch_sync?

寵の児 提交于 2019-12-13 02:38:29

问题


I have some questions about dispatch_barrier and dispatch_sync. Here's the code:

- (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;
}

In addPhoto method, it uses dispatch_barrier_async. In photos method, it uses dispatch_sync. Can I replace the dispatch_barrier_async into dispatch_sync? If yes, is this way popular in practical programming? If no, please tell me why. Thanks a lot!


回答1:


Actually, in this example, replacing dispatch_barrier_async with dispatch_sync will produce unexpected behavior. You have concurrent queue to access to photos - it means, it lets you run several operations simultaneously. It is okay to read _photosArray from as many places, as you want in one time. But bad things happens, if you'll try to change its contents, while somebody reads it. Here comes dispatch_barrier_async - it lets you, so to say, add "seriality" to concurrent queue. Block dispatched that way will wait, till all other operations stops, starts, and while its execution no one will start no any operations on that queue.

It is classic Readers-writers problem.

Please, feel free to ask, if something left unexplained

Update 1

You cannot use async functions in photos method. dispatch_sync makes your method wait until task executed.

By numbers I marked execution flow

- (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
}

If you use 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 calls will run simultaneously.

For example, you have thread1 and thread2. They hold the same object object. In some place they simultaneously makes call

thread1 : NSLog(@"%@", [object photos]); thread2 : NSArray *photos = [object photos];

This calls will be performed concurrently (i. e. in the same time), but synchronously - threads freeze till they get photos.

However, if you make something like this

thread2 : NSArray *photos = [object addPhoto:newPhoto]; thread1 : NSLog(@"%@", [object photos]);

your thread1 freezes until photo added to an array. But, thread2 will not wait, till photo actually added - it just continue execution.



来源:https://stackoverflow.com/questions/32647214/gcd-dispatch-barrier-or-dispatch-sync

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!