LeeRQ
LeeRQ

Reputation: 79

GCD why to use dispatch_sync when I read shared resource

I have some question about use dispatch_sync when I read a shared resource. I have searched several questions on Stack Overflow (such as: GCD dispatch_barrier or dispatch_sync?), but I didn't found an exact answer.

I don't understand that why to use

- (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];
    });
    return array;
}

I know why to use dispatch_barrier_async,but I don't know why to use dispatch_sync when I read _photosArray, I guess the write operation of _photosArray is in the self.concurrentPhotoQueue, so the read operation of _photosArray also need in the self.concurrentPhotoQueue or else use dispatch_sync in order to achieve multi-read?

What will happen if I don't use dispatch_sync when I do read operation? such as:

- (NSArray *)photos
{
    __block NSArray *array;
    array = [NSArray arrayWithArray:_photosArray];
    return array;
}

Thank you very much!

Upvotes: 2

Views: 236

Answers (1)

clemens
clemens

Reputation: 17721

Probably concurrentPhotoQueue is a serial queue. The main reason for concurrentPhotoQueue is to synchronize the access to the photos array.

Since it is serial all accesses from this queue are serialized, and no race conditions may occur if there are no accesses from other queues / threads in your app.

Writing access may be asynchronous because the writer needs no result of the writing operation in general. But reading must be done synchronously, because the caller has to wait for the result. If your photos method would use dispatch_async it would write the result to array after the photos method has returned. Thus, photos always would return nil.

Your unsynchronized version of photos might produce a race condition: _photosArray could be modified while it copies its contents, such that the number of copied items and the length of the array differ. This could lead to a crash inside of arrayWithArray:.

Upvotes: 3

Related Questions