当同步/异步与串行/并发队列混合时,调度程序如何工作?

2024-02-16

在 Grand Central Dispatch 中,调度程序如何处理不同的队列(serial and concurrent)当使用dispatch_sync函数和dispatch_async功能?


首先我们需要两种类型queue: one serial和一个同时:

dispatch_queue_t serialQueue =
dispatch_queue_create("com.matteogobbi.dispex.serial_queue", DISPATCH_QUEUE_SERIAL);

dispatch_queue_t concurrentQueue =
dispatch_queue_create("com.matteogobbi.dispex.concurrent_queue", DISPATCH_QUEUE_CONCURRENT);

所以,我们可以从第一个实验开始,使用串行队列和所有dispatch_async函数将我们的块添加到队列中:

/* Dispatch async with serial queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Serial");

NSLog(@"block 1 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_async(serialQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:异步 - 队列:串行

2014-04-08 14:43:16.468 dispex[4346:60b] 添加块 1

2014-04-08 14:43:16.468 dispex[4346:60b] 块 2 添加

2014-04-08 14:43:16.468 dispex[4346:1303] 块 1

2014-04-08 14:43:16.469 dispex[4346:1303] 块 2

2014-04-08 14:43:16.468 dispex[4346:60b] 块 3 添加

2014-04-08 14:43:16.469 dispex[4346:1303] 块 3

2014-04-08 14:43:16.469 dispex[4346:60b] 块 4 添加

2014-04-08 14:43:16.469 dispex[4346:1303] 块 4

2014-04-08 14:43:16.469 dispex[4346:60b] 块 5 添加

2014-04-08 14:43:16.470 dispex[4346:60b] 块 6 添加

2014-04-08 14:43:16.470 dispex[4346:1303] 块 5

2014-04-08 14:43:16.471 dispex[4346:60b] 添加了块 7

2014-04-08 14:43:16.471 dispex[4346:1303] 块 6

2014-04-08 14:43:16.471 dispex[4346:1303] 块 7

2014-04-08 14:43:16.471 dispex[4346:60b] 块 8 添加

2014-04-08 14:43:16.471 dispex[4346:1303] 块 8

2014-04-08 14:43:16.471 dispex[4346:60b] 添加了第 9 块

2014-04-08 14:43:16.472 dispex[4346:60b] 块 10 添加

2014-04-08 14:43:16.472 dispex[4346:1303] 块 9

2014-04-08 14:43:16.472 dispex[4346:1303] 块 10

2014-04-08 14:43:16.472 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

如您所见,该块已添加到队列中,但是同时调度员开始执行它们。这是一个特点dispatcher_async函数,即将块添加到队列中,无需等待它们完成执行。换句话说,如果您正在使用dispatch_async在函数中,函数立即返回,同时块正在执行。这非常有用!在此示例中,我使用 NSLog 来报告块何时添加到队列中,因此这确实会导致执行速度变慢并导致日志

添加了所有块

在最后。但正如我们稍后将看到的,如果没有日志,它将被写在开头。由于我们使用的是串行队列,因此块按照添加的顺序执行。

Next:

/* Just wait before begin with the next test */
dispatch_group_wait(group_async_serial, DISPATCH_TIME_FOREVER);


/* Dispatch sync with serial queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Serial");

NSLog(@"block 1 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_sync(serialQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:同步 - 队列:串行

2014-04-08 14:43:16.473 dispex[4346:60b] 块 1 添加

2014-04-08 14:43:16.474 dispex[4346:60b] 块 1

2014-04-08 14:43:16.474 dispex[4346:60b] 块 2 添加

2014-04-08 14:43:16.474 dispex[4346:60b] 块 2

2014-04-08 14:43:16.475 dispex[4346:60b] 块 3 添加

2014-04-08 14:43:16.475 dispex[4346:60b] 块 3

2014-04-08 14:43:16.475 dispex[4346:60b] 块 4 添加

2014-04-08 14:43:16.475 dispex[4346:60b] 块 4

2014-04-08 14:43:16.476 dispex[4346:60b] 块 5 添加

2014-04-08 14:43:16.476 dispex[4346:60b] 块 5

2014-04-08 14:43:16.476 dispex[4346:60b] 块 6 添加

2014-04-08 14:43:16.477 dispex[4346:60b] 块 6

2014-04-08 14:43:16.477 dispex[4346:60b] 块 7 添加

2014-04-08 14:43:16.477 dispex[4346:60b] 块 7

2014-04-08 14:43:16.477 dispex[4346:60b] 块 8 添加

2014-04-08 14:43:16.478 dispex[4346:60b] 块 8

2014-04-08 14:43:16.478 dispex[4346:60b] 添加了第 9 块

2014-04-08 14:43:16.478 dispex[4346:60b] 块 9

2014-04-08 14:43:16.479 dispex[4346:60b] 块 10 添加

2014-04-08 14:43:16.479 dispex[4346:60b] 块 10

2014-04-08 14:43:16.479 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

在这个例子中我们使用dispatch_sync函数与串行队列。很容易看出,当前一个块执行完毕时,所有块都会被添加。这是一个特点dispatch_sync。换句话说,直到块执行完毕后,该函数才会返回。由于这是一个串行队列,因此这里的顺序也受到尊重。

Next:

/* Dispatch async with concurrent queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Concurrent");
dispatch_group_t group_async_concurrent = dispatch_group_create();

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 1");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 2");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 3");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 4");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 5");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 6");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 7");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 8");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 9");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 10");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 11");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 12");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 13");
});

dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
    NSLog(@"block 14");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:异步 - 队列:并发

2014-04-08 14:43:16.480 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

2014-04-08 14:43:16.480 dispex[4346:1303] 块 1

2014-04-08 14:43:16.480 dispex[4346:3503] 块 2

2014-04-08 14:43:16.480 dispex[4346:3603] 块 3

2014-04-08 14:43:16.480 dispex[4346:3803] 块 5

2014-04-08 14:43:16.480 dispex[4346:3703] 块 4

2014-04-08 14:43:16.480 dispex[4346:3903] 块 6

2014-04-08 14:43:16.480 dispex[4346:3a03] 块 7

2014-04-08 14:43:16.480 dispex[4346:3b03] 块 8

2014-04-08 14:43:16.482 dispex[4346:1303] 块 9

2014-04-08 14:43:16.483 dispex[4346:3503] 块 10

2014-04-08 14:43:16.483 dispex[4346:3803] 块 12

2014-04-08 14:43:16.483 dispex[4346:3703] 块 13

2014-04-08 14:43:16.483 dispex[4346:3903] 块 14

2014-04-08 14:43:16.483 dispex[4346:3603] 块 11

正如我之前所说,这里我展示了如何工作dispatch_async但有一个并发队列。 这真的很有趣,因为没有 NSLog 显示何时添加块,您可以看到在执行第一个块之前如何添加所有块。这种行为不是恒定的. 可能会发生 block1 被执行并且紧随其后dispatch_asyncfinish将所有块添加到队列中,然后继续执行其他块。另一件需要注意的事情是,块是并发执行的,因此它们不遵守添加顺序,而且这种行为不是恒定的,而是取决于 CPU 使用率、性能和许多其他因素。

Next:

/* Just wait before begin with the next test */
dispatch_group_wait(group_async_concurrent, DISPATCH_TIME_FOREVER);


/* Dispatch sync with concurrent queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Concurrent");

NSLog(@"block 1 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 1");
});

NSLog(@"block 2 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 2");
});

NSLog(@"block 3 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 3");
});

NSLog(@"block 4 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 4");
});

NSLog(@"block 5 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 5");
});

NSLog(@"block 6 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 6");
});

NSLog(@"block 7 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 7");
});

NSLog(@"block 8 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 8");
});

NSLog(@"block 9 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 9");
});

NSLog(@"block 10 added");
dispatch_sync(concurrentQueue, ^{
    NSLog(@"block 10");
});

NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");

调度:同步 - 队列:并发

2014-04-08 14:43:16.486 dispex[4346:60b] 块 1 添加

2014-04-08 14:43:16.486 dispex[4346:60b] 块 1

2014-04-08 14:43:16.487 dispex[4346:60b] 块 2 添加

2014-04-08 14:43:16.487 dispex[4346:60b] 块 2

2014-04-08 14:43:16.487 dispex[4346:60b] 块 3 添加

2014-04-08 14:43:16.488 dispex[4346:60b] 块 3

2014-04-08 14:43:16.488 dispex[4346:60b] 块 4 添加

2014-04-08 14:43:16.488 dispex[4346:60b] 块 4

2014-04-08 14:43:16.489 dispex[4346:60b] 块 5 添加

2014-04-08 14:43:16.489 dispex[4346:60b] 块 5

2014-04-08 14:43:16.489 dispex[4346:60b] 块 6 添加

2014-04-08 14:43:16.489 dispex[4346:60b] 块 6

2014-04-08 14:43:16.490 dispex[4346:60b] 块 7 添加

2014-04-08 14:43:16.490 dispex[4346:60b] 块 7

2014-04-08 14:43:16.490 dispex[4346:60b] 块 8 添加

2014-04-08 14:43:16.491 dispex[4346:60b] 块 8

2014-04-08 14:43:16.491 dispex[4346:60b] 添加了第 9 块

2014-04-08 14:43:16.491 dispex[4346:60b] 块 9

2014-04-08 14:43:16.492 dispex[4346:60b] 块 10 添加

2014-04-08 14:43:16.492 dispex[4346:60b] 块 10

2014-04-08 14:43:16.492 dispex[4346:60b] 所有块都添加到队列中 --> 函数返回

最后,这里我们使用了dispatch_sync with 并发队列。它看起来完全等于同步/串行对。在这种情况下就是这样。这种行为的原因是,如果队列是并发的,它没有其他块要执行,因为我们正在使用同步调度程序,因此它会等待添加下一个块,直到实际执行完毕为止。这种类型的情侣(同步/并发) 如果我们也添加到队列中,则很有用,块dispatch_async。在这种情况下,调度程序可以将其他块添加到要执行的队列中。

希望这个迷你演示有用;)

Cheers!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当同步/异步与串行/并发队列混合时,调度程序如何工作? 的相关文章

  • Swift 3:如何访问48字节CFData中matrix_float3x3的值?

    我正在尝试访问内在矩阵answer https stackoverflow com a 48159895 9296667 通过运行下面的命令 我能够得到一个 48 字节的任意对象 https developer apple com docu
  • mgwt - 以编程方式改变方向

    是否可以在 gwt mgwt 应用程序中更改强制执行特定的屏幕方向 可以说我希望用户始终以横向模式使用应用程序 这取决于 是作为phonegap应用程序 而不是在浏览器内部 如果您作为 Web 应用程序运行 则不需要t get any co
  • UIStackView分布均匀填充

    所以 我有一个UIStackView其中包含四 4 UIViews 如果我删除其中一 1 个UIViews 其他三 3 个将填满UIStackView 我的问题 如何添加最大高度UIView这样它就不会填满整个空间UIStackView即使
  • 使用 NSString 进行 UTF8 解码

    我是 Objective C 新手 尝试使用以下示例将格式错误的 UTF8 编码 NSString 转换为格式良好的字符串苹果文档 http developer apple com library mac documentation Coc
  • iOS - 如何在 swift 中使用 `NSMutableString`

    我已经看过这段 Objective C 代码 但我很难在 swift 中做同样的事情 NSMutableAttributedString res self richTextEditor attributedText mutableCopy
  • .showsPhysics 内存泄漏

    我最近花了 5 个小时尝试调试 Spritekit 应用程序中的内存泄漏 应用程序启动后 我注意到内存使用量略有上升 我花了 5 个小时中的 3 个小时挖掘参考资料 了解强与弱的关系ARC https developer apple com
  • 如何在iOS中处理1到3个手指的滑动手势

    我使用以下代码来处理代码中的 1 根手指滑动 UISwipeGestureRecognizer swipe UISwipeGestureRecognizer alloc initWithTarget self action selector
  • 如何从 ContentView 外部显示 SwiftUI 警报?

    我正在构建 Swift 应用程序 并试图找出如何显示警报 我有一个单独的 swift 文件正在执行一些计算 并且在某些条件下我希望它向用户显示警报 基本上告诉他们出了问题 然而 我见过的大多数例子都要求警报在ContentView或以其他方
  • `navigator.geolocation.getCurrentPosition()` 在 iOS PWA 上挂起

    我有这个片段 const getCurrentPosition gt new Promise
  • 从 UIPickerView 的选定行设置 UIButton 的标题

    详细场景是这样的 我使用循环创建 10 个按钮并设置 0 9 的标签 点击每个按钮时 我将调用 UIPickerView 在其中加载来自不同数组的数据 到这里我就得到了预期的结果 但我希望 pickerView 中选定的行应设置为相应按钮的
  • 如何从 SDK 实现每个会话的 Google Places 自动完成功能?

    是否可以从 Android 和 iOS 应用程序的 place sdk 实现基于会话的自动完成 根据 6 月 11 日生效的新 Google 地图框架定价 对自动完成的请求可以分为基于击键 会话的请求 我找不到描述实施步骤的文档 除了这个参
  • 如何保护 iOS 应用程序免受任何操作系统攻击(在越狱设备上)

    我希望保护我的应用程序数据 以防任何操作系统攻击或越狱 iOS 设备上的未经授权的访问 在这种情况下 有什么方法可以检测此类威胁并保护应用程序数据 虽然我同意 jrturton 的说法 但如果您有想要保护的关键数据免受流氓应用程序 而不是用
  • Objective-C UILabel 作为超链接

    我正在尝试做一个UILabel一个链接UIWebView 我怎样才能做一个UILabel作为超链接 您可以使用 UITapGestureRecognizer 它将实现与您想要的类似的功能 UILabel myLabel UILabel al
  • 使用未解析的标识符“FlurryAdInterstitial”

    我正在尝试整合Flurry Interstitial Ads使用cocoapods in Swift and Xcode 7 1 1 我正在关注开发人员雅虎网站上的此文档 https developer yahoo com flurry d
  • UIViewControllerAnimatedTransitioning:旋转更改后黑屏片段

    我已经创建了一个视图控制器转换 只要我不更改设备方向 一切都正常 图 1 显示了应有的屏幕 然后我切换到下一个视图控制器 在其中更改方向 现在我回到第一个视图控制器并再次切换方向 然后我得到的结果如图 2 所示 出现黑色边框 请不要介意屏幕
  • iOS 7 上 Safari 浏览器的用户代理

    我只想在带有 Safari 浏览器的 iPhone 和 iPod 中打开我的网站 对于 Chrome Dolphin 等任何其他浏览器 它不应该打开 但目前我从几乎所有设备获得相同的用户代理 对于Safari User Agent Stri
  • 调整 UIImage 的大小而不将其完全加载到内存中?

    我正在开发一个应用程序 用户可以在其中尝试加载非常非常大的图像 这些图像首先在表格视图中显示为缩略图 我的原始代码会在大图像上崩溃 因此我重写它以首先将图像直接下载到磁盘 是否有一种已知的方法可以调整磁盘上图像的大小 而无需通过以下方式将其
  • 访问目标 c 中的类方法。使用 self 还是类名?

    我正在学习 iOS 编程 并且对以下有关关键字 self 的使用的代码感到困惑 据我了解 self就像Java的this 它指的是当前实例 当我想调用类方法时 通常的方式应该是这样 PlayingCard validSuits 但是侵入实例
  • TableViewController 的 viewDidLoad 未触发

    我一直在关注这个tutorial http www appcoda com ios programming sidebar navigation menu 有一个滑出式菜单 我添加了一个 TableViewController 它将显示文章
  • 如何解决 Xcode 5 中的红色(已移动)文件?

    在 Xcode 4 中 当您要移动文件时 可以通过单击右侧菜单中的按钮并通过 Finder 选择新位置来解析文件的新位置 在 Xcode 5 中 右侧菜单中没有按钮 我还没有找到任何方法通过右键单击文件或顶部菜单栏选项来指定文件的新位置 在

随机推荐