A barrier on queue does not affect its target queue.
This is most easily demonstrated empirically. For example:
- (void)experiment {
dispatch_queue_t queue1 = dispatch_queue_create("1", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue2 = dispatch_queue_create_with_target("2", DISPATCH_QUEUE_CONCURRENT, queue1);
dispatch_async(queue1, ^{
[self taskOnQueue:1 taskNumber:1 color:1];
});
dispatch_async(queue2, ^{
[self taskOnQueue:2 taskNumber:2 color:0];
});
dispatch_barrier_async(queue2, ^{
[self taskOnQueue:2 taskNumber:3 color:0];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_async(queue2, ^{
[self taskOnQueue:2 taskNumber:4 color:0];
});
dispatch_async(queue1, ^{
[self taskOnQueue:1 taskNumber:5 color:1];
});
});
}
Tasks 1-3 are immediately dispatched, and tasks 4 and 5 are dispatched 0.5 seconds later. Task 3 is using a barrier. Tasks 1 and 5 are on queue1
, and tasks 2-4 are on queue2
. All tasks take one second each.
That results in the following. (I manually highlighted those task numbers to make this more clear.)

You can see that task #5 on queue 1 starts as soon as it's queued, even though (a) it was the last task queued, and (b) queue 2 has a barrier on task #3. The second queue respects the barrier on task 3, though.
FYI, this these are the utility methods that generate those points of interest ranges:
- (void)taskOnQueue:(uint32_t)code taskNumber:(uint32_t)arg1 color:(uint32_t)arg4 {
[self pointOfInterest:code arg1:arg1 color:arg4 block:^{
[NSThread sleepForTimeInterval:1];
}];
}
- (void)pointOfInterest:(uint32_t)code arg1:(uint32_t)arg1 color:(uint32_t)arg4 block:(void (^)(void))block {
kdebug_signpost_start(code, arg1, 0, 0, arg4);
block();
kdebug_signpost_end(code, arg1, 0, 0, arg4);
}
NB: The converse is a completely different issue. Queues will be affected if their target queue has a barrier. If the target queue is blocked (for example, if you change task 3 to run with a barrier on the target queue, queue1
, instead), then tasks on the second queue will wait for its target queue to free up:
- (void)experiment2 {
dispatch_queue_t queue1 = dispatch_queue_create("1", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue2 = dispatch_queue_create_with_target("2", DISPATCH_QUEUE_CONCURRENT, queue1);
dispatch_async(queue1, ^{
[self taskOnQueue:1 taskNumber:1 color:1];
});
dispatch_async(queue2, ^{
[self taskOnQueue:2 taskNumber:2 color:0];
});
dispatch_barrier_async(queue1, ^{ // changed to queue 1
[self taskOnQueue:1 taskNumber:3 color:1];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_async(queue2, ^{
[self taskOnQueue:2 taskNumber:4 color:0];
});
dispatch_async(queue1, ^{
[self taskOnQueue:1 taskNumber:5 color:1];
});
});
}
That will result in:

Here, task 3 was dispatched with a barrier (where that first Ⓢ signpost is), and not only did it not start until task 1 was done on the target queue, but task 4 (running on the second queue) on the second queue (dispatched where that second Ⓢ signpost is) waited for that barrier on its queue's target queue, too, just like task 5 did.