【问题标题】:FIFO serial queue using GCD使用 GCD 的 FIFO 串行队列
【发布时间】:2012-12-17 05:11:19
【问题描述】:

我正在尝试为我工作的公司创建一个(网络)同步阵列。虽然网络部分工作正常,但我已经陷入了一个问题。

我的愿望是使用dispatch_create_queue 创建一个新队列,我将向其中添加两个在主线程上运行但以串行方式运行的块,这意味着首先第一个块必须运行,然后是第二个,并且永远不会并行。

我已经阅读了苹果文档,但至少可以说令人困惑。

  • 当我使用dispatch_queue_create 创建队列,然后使用dispatch_sync 添加块(在它们被定义之后)时,我发现该块仍在主线程上执行。

  • 当使用dispatch_async 时,块不在主线程上执行。

  • 当我尝试使用 dispatch_sync 添加两个块时,它们会被永久阻止。

  • 只有在调用dispatch_async 时,两个块似乎都运行良好并且脱离了主线程。

但是,我之所以选择 GCD 和同步方法,是因为我的印象是我正在创建一个新队列(因此​​是一个新线程),并且向该队列添加块只会阻塞一个,直到另一个执行完毕。是不是这样,还是创建队列并不能保证代码不会在主线程上运行?

【问题讨论】:

    标签: objective-c objective-c-blocks grand-central-dispatch fifo


    【解决方案1】:

    这是 GCD 中的 FIFO 队列:

    dispatch_queue_t serialQueue = dispatch_queue_create("com.blah.queue", DISPATCH_QUEUE_SERIAL);
    
    ...
    dispatch_async(serialQueue, ^{
        //block1
    });
    
    dispatch_async(serialQueue, ^{
        //block2
    });
    

    【讨论】:

    • dispatch_async 使得调度调用本身在块完成之前不会阻塞。如果使用 dispatch_sync,任务本身会在队列所在的任何线程中执行,但会阻塞当前线程,直到任务完成。我认为这不是你需要的。
    • 所有调度队列都是先进先出的。这意味着只要你重用同一个队列,块执行的顺序就被确定并保证不锁定,因此是线程安全的。
    • @gasher729 即使并发队列在技术上也是先进先出。来自 Apple 关于并发队列的文档:“并发队列(也称为一种全局调度队列)同时执行一个或多个任务,但任务仍然按照它们添加到队列中的顺序启动。”
    • @jmstone 并发队列不会是唯一的吗?由于它们并行运行,您不能保证第一个工作将是第一个工作?我在调用 Google 的 GeoCode API 时遇到过这种情况,我在其中发送了一系列存储在数组(地址)中的查询,并且返回的 JSON 并没有按照我发送的顺序返回。 IE。按顺序发送地址1,地址2,地址3,返回的位置数据可能是位置2,位置1,位置3...
    • @PruitIgoe FIFO 并不意味着 FIFC(先进先完成)。就像我上面提到的,FIFO 顺序只是保证任务按照它们添加到队列中的顺序启动。这并不意味着它们以相同的顺序完成,正如您给出的示例所证明的那样。
    猜你喜欢
    • 2013-06-29
    • 2012-06-12
    • 2022-08-23
    • 2016-06-04
    • 2013-10-11
    • 2021-09-28
    • 2014-04-28
    • 2013-03-15
    • 1970-01-01
    相关资源
    最近更新 更多