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!
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With