GCD dispatch_sync优先于先前排队的dispatch_async

时间:2014-11-07 18:09:44

标签: multithreading grand-central-dispatch

我有一个包装数据模型的类,并由多个线程访问/修改。我需要确保对数据模型的修改是同步的。我正在使用dispatch_queue_create(...,DISPATCH_QUEUE_SERIAL)。这对我的需求非常有效。

我班上的大多数方法都在内部调用" dispatch_async(queue,^ {...});"。我需要在一些地方返回快照结果。这是一个简单的示例:

- (NSArray*) getSomeData {
    __block NSArray* result = nil;

    dispatch_sync(queue, ^{
         ... Do Stuff ...
         result = blah.blah;
    }

    return result;
}

现在,让我们假设5"异步任务"排队,一个正在执行。现在a"同步"任务已安排。什么时候"同步任务"执行?

我希望发生的是"同步任务"在任何未决的"异步任务"之前执行。这是默认情况下会发生什么?如果没有,是否有一种方法可以优先排队"同步任务"?

顺便说一句,

我知道我可以设置整体队列优先级,但这不是这个问题的内容。对我来说队列优先正常就好了。我只希望我的同步任务在任何挂起的异步任务之前发生。

1 个答案:

答案 0 :(得分:2)

"首先执行同步任务&#34>不是通用设置。或者用于设置单个队列中排队的块之间的相对优先级。回顾一下可能很明显的事情,串行队列将像队列一样工作:先进先出。也就是说,很容易想到如何使用多个队列和目标来实现这种效果。例如:

realQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
asyncOpsQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(asyncOpsQueue, realQueue);

for (NSUInteger i = 0; i < 10; i++)
{
    dispatch_async(asyncOpsQueue, ^{
        NSLog(@"Doing async work block %@", @(i));
        sleep(1);
    });
}

// Then whenever you have high priority sync work to do, stop the async
// queue, do your work, and then restart it.
dispatch_suspend(asyncOpsQueue);
dispatch_sync(realQueue, ^{
    NSLog(@"Doing sync work block");
});

dispatch_resume(asyncOpsQueue);

要知道的是,一旦开始,执行区块就无法有效地取消/暂停/终止(从外部)。因此,在同步块可以启动之前,任何在飞行中的异步排队块都必须运行完成,但这种定位方式允许您暂停异步块流并注入同步块。请注意,您执行同步功能块并不重要。它可以同样容易地成为高优先级的异步块,但在这种情况下,您可能希望将dispatch_resume移动到块本身。