【问题标题】:How does dispatch_barrier_async interact with the target queue?dispatch_barrier_async 如何与目标队列交互?
【发布时间】:2019-05-21 05:11:54
【问题描述】:

鉴于以 queue1 为目标创建 queue2 (queue2 = dispatch_queue_create_with_target(name, attr, queue1))...

如果两个队列都是并发的,queue2 上的dispatch_barrier_async 是只等待 queue2 为空,还是也等待目标队列?当两个队列都有各自的barrier block排队时,queue2的barrier block是否优先?

【问题讨论】:

    标签: ios grand-central-dispatch


    【解决方案1】:

    队列上的屏障不会影响其目标队列。

    这是最容易通过经验证明的。例如:

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

    任务 1-3 立即分派,任务 4 和 5 在 0.5 秒后分派。任务 3 正在使用屏障。任务 1 和 5 位于 queue1,任务 2-4 位于 queue2。所有任务都需要一秒钟。

    结果如下。 (我手动突出显示了这些任务编号以使这一点更清楚。)

    您可以看到队列 1 上的任务 #5 在排队时立即启动,即使 (a) 它是排队的最后一个任务,并且 (b) 队列 2 对任务 #3 有障碍。不过,第二个队列尊重任务 3 的障碍。

    仅供参考,这些是生成points of interest 范围的实用方法:

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

    注意:反过来是一个完全不同的问题。如果目标队列有障碍,队列受到影响。如果目标队列被阻塞(例如,如果您将任务 3 更改为使用目标队列上的屏障运行,queue1),则第二个队列上的任务将等待其目标队列释放:

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

    这将导致:

    在这里,任务 3 被分派了一个屏障(第一个 Ⓢ 路标所在的位置),它不仅在目标队列上的任务 1 完成后才开始,而且任务 4(在第二个队列上运行)在第二个队列(在第二个 Ⓢ 路标所在的位置调度)也在其队列的目标队列上等待该屏障,就像任务 5 所做的那样。

    【讨论】:

    • 你真的付出了额外的努力。谢谢。我最近才开始使用并发队列,发现文档略有不足,尽管这是一种直观的行为。
    猜你喜欢
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 2011-09-18
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多