I'm not sure if this broke in xcode8 beta 5. Look at this code. Do you think it should print "A" first, or "B" first?
let q = DispatchQueue(label: "q", attributes: .concurrent)
q.async(flags: .barrier) {
Thread.sleep(forTimeInterval: 0.25)
print("A")
}
q.sync {
print("B")
}
Because of the .barrier
, I think it should block the concurrent queue and print "A", "B", but it does not in the latest xcode beta.
Bug? Misunderstanding of .barrier? What do you think?
please note: I know this would print in the expected order if I used a serial queue--this is a tiny part of a much larger system and I need to understand this behavior in isolation.
Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue. Queues (also known as a type of global dispatch queue) execute one or more tasks concurrently, but tasks are still started in the order in which they were added to the queue.
DispatchGroup allows for aggregate synchronization of work. It can be used to submit multiple different work items or blocks and track when they all complete, even though they might run on different queues.
barrier flag means that it will wait until every currently running block in the queue is finished executing before it executes. Other blocks will queue up behind it and be executed when the barrier dispatch is done. When the barrier is executing, it essentially acts as a serial queue.
Overview. Use a barrier to synchronize the execution of one or more tasks in your dispatch queue. When you add a barrier to a concurrent dispatch queue, the queue delays the execution of the barrier block (and any tasks submitted after the barrier) until all previously submitted tasks finish executing.
This was a bug fixed in beta 6.
In beta 5, not only does it not behave the way you'd expect, but the .onQueueAsBarrier
precondition fails, too. The problem would appear to be buried in async
with the .barrier
option, because if you perform it via equivalent Objective-C API, dispatch_barrier_async
, it works fine, e.g.:
let q = DispatchQueue(label: "q", attributes: .concurrent)
BarrierExperiment.dispatchBarrierAsync(q) {
dispatchPrecondition(condition: .onQueueAsBarrier(q))
Thread.sleep(forTimeInterval: 0.25)
print("A")
}
q.async() {
print("B")
}
Where
@interface BarrierExperiment : NSObject
+ (void)dispatchBarrierAsync:(dispatch_queue_t)queue block:(void (^)())block;
@end
@implementation BarrierExperiment
+ (void)dispatchBarrierAsync:(dispatch_queue_t)queue block:(void (^)())block {
dispatch_barrier_async(queue, block);
}
@end
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