在GCD(中央调度)中创建dispatch_queues多少算太多?

2024-03-13

Mike Ash 有一篇关于用 Swift 构建的轻量级通知系统的精彩文章:(https://www.mikeash.com/pyblog/friday-qa-2015-01-23-lets-build-swift-notifications.html https://www.mikeash.com/pyblog/friday-qa-2015-01-23-lets-build-swift-notifications.html).

基本思想是创建可以“监听”的对象,即在发生某些状态更改时调用回调。为了使其线程安全,创建的每个对象都拥有自己的dispatch_queue。 dispatch_queue 只是用来控制临界区:

dispatch_sync(self.myQueue) {
    // modify critical state in self
}

而且它可能不会引起激烈的争论。我有点震惊的是every您创建的可监听的单个对象会创建自己的调度队列,只是为了锁定几行代码。

一张海报建议 OS_SPINLOCK 会更快、更便宜;也许吧,但它肯定会使用更少的空间。

如果我的程序创建了数百或数千(甚至数万个对象),我是否应该担心创建这么多调度队列?也许大多数人都不会被倾听,但有些人可能会。

两个对象不会互相阻塞,即具有单独的锁,这当然是有道理的,通常我不会三思而后行,比如在每个对象中嵌入一个 pthread_mutex ,而是嵌入整个调度队列?真的可以吗?


好吧,Grand Central Dispatch 的文档 https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/doc/uid/TP40008079关于调度队列的内部工作原理和确切成本相当模糊,但它确实指出:

GCD 提供并管理 FIFO 队列,您的应用程序可以向其中以块对象的形式提交任务。提交到调度队列的块在完全由系统管理的线程池上执行。

因此,听起来队列只不过是通过线程池对块进行排队的接口,因此在空闲时对性能没有/最小的影响。

概念文档还指出: https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1

您可以根据需要创建任意数量的串行队列

这听起来绝对是创建串行调度队列并使其闲置的成本几乎微不足道。

此外,我决定在具有一些 Open GL 内容的应用程序上测试创建 10,000 个串行和并发调度队列,并没有发现性能受到任何影响,FPS 保持不变,并且只使用了额外的 4MB RAM(单个队列约 400 字节)。

在使用 OS_SPINLOCK 而不是调度队列方面,Apple 是very在它的文档中清楚地说明了迁移线程 https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/ThreadMigration/ThreadMigration.html#//apple_ref/doc/uid/TP40008091-CH105-SW1GCD 比使用标准锁更有效(至少在竞争情况下)。

用队列替换基于锁的代码消除了许多与锁相关的惩罚并且还简化了剩余的代码。您可以创建一个队列来序列化访问该资源的任务,而不是使用锁来保护共享资源。队列不会施加与锁相同的惩罚。例如,对任务进行排队不需要陷入内核来获取互斥体。

但值得注意的是,如果您不使用队列,则可以随时释放它,并在稍后需要再次使用时重新创建它(如果您担心内存问题)。


TL;DR

调度队列是最佳选择。您不必太担心创建大量队列而不使用它们,而且它们肯定比锁更有效。

Edit:您实际上发现自旋锁在无竞争的情况下速度更快,因此您可能会想使用它!

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

在GCD(中央调度)中创建dispatch_queues多少算太多? 的相关文章

  • 在Java中,如何在每次进入或退出给定对象的监视器时记录一条消息?

    我正在尝试调试一些使用一些自定义引用计数 锁定的 C Java 绑定 我想让 JVM 在每次给定对象进入或退出其监视器时打印一条消息 有什么办法可以做到这一点吗 基本上 我想要这个 synchronized lock System out
  • Android SurfaceView onDraw 停止 Thread.join()

    我正在尝试开发一款游戏SurfaceView 问题是当我想摧毁thread用方法surfaceDestroyed 应用程序停止于thread join 但如果不这样做 绘制画布 canvas drawColor Color GREEN 在里
  • 使用来自不同线程的实时数据更新 QTableView 的最佳策略

    我的应用程序现在启动几个线程 如 5 10 个 来从不同源收集数据 它们与主 GUI 线程分离 因此我在 GUI 中感觉不到任何缓慢 并且我可以在后台线程工作时继续工作 一切都很棒 但现在我希望能够在我的主 GUI 中的 QTableVie
  • Socket.*Async 方法是线程化的吗?

    我目前正在尝试找出最小化 TCP 主服务器中使用的线程数量的最佳方法 以便最大限度地提高性能 由于我最近阅读了大量 C 5 0 的新异步功能 异步并不一定意味着多线程 这可能意味着将有限状态对象分成较小的块 然后通过交替与其他操作一起进行处
  • Lockfree 标准集合和教程或文章

    有人知道用于无锁常用数据类型的实现 即源代码 的好资源吗 我正在考虑列表 队列等 锁定实现非常容易找到 但我找不到无锁算法的示例以及 CAS 的工作原理以及如何使用它来实现这些结构 查看 Julian M Bucknall 的博客 他 详细
  • Jupyter Notebook 中的多处理与线程

    我试图测试这个例子here https ipywidgets readthedocs io en stable examples Widget 20Asynchronous html将其从线程更改为多处理 在 jupyter Noteboo
  • 什么时候 Thread.sleep(1000) 睡眠时间少于 1000 毫秒?

    在这篇有趣的文章中程序员对时间的看法是错误的 http infiniteundo com post 25509354022 more falsehoods programmers believe about time wisdom 其中之一
  • .NET 中的线程中止

    我有一个线程正在分析文件并对数据库进行事务调用 每个事务都有一个审计条目作为其事务的一部分 调用 Thread Abort 来停止文件的处理有什么大问题吗 而不是到处散布丑陋的安全点 文件将在 Abort 调用后关闭 明显的问题是放弃交易的
  • 内存不一致与线程交错有何不同?

    我正在编写一个多线程程序 正在研究是否应该使用volatile对于我的布尔标志 关于并发性的文档 oracle Trail 没有解释任何关于memory consistency errors以外 当不同的线程有内存一致性错误时 就会发生内存
  • 当应用程序终止时,我可以安全地依赖 Threads 中的 IsBackground 吗?

    我正在 GUI 中运行一些后台线程 目前 我正在实现个人线程取消代码 但线程中有 IsBackground 属性 根据 MSDN 它们会自行取消 我知道它将进入 Thread Abort 这很令人讨厌 但是在这个后台线程中没有任何事情需要我
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 使用任务的经典永无止境的线程循环?

    给出了一个非常常见的线程场景 宣言 private Thread thread private bool isRunning false Start thread new Thread gt NeverEndingProc thread S
  • 重构——套接字中的良好实践——简单的服务器-客户端 Swing 应用程序

    我使用单例和观察者模式编写了一个带有 Swing 接口的简单服务器 客户端程序 每个客户端都连接到服务器并可以发送消息 服务器将其收到的消息转发给其余的客户端 客户端使用 GUI 允许它们随时连接和断开与服务器的连接 该程序运行得很好 因为
  • 为什么一个线程会中断另一个线程[重复]

    这个问题在这里已经有答案了 在Java多线程应用程序中 我们处理InterruptedThreadException 如果另一个线程中断当前线程 则会抛出此异常 现在 当另一个线程知道它将导致异常时 它可能想要中断当前线程的原因是什么 很多
  • 在多线程环境中,Collections.sort 方法有时会抛出 ConcurrentModificationException。列表没有进行结构性修改

    package CollectionsTS import java util ArrayList import java util Collections import java util HashSet import java util
  • 不支持 STA 线程上多个句柄的 WaitAll

    为什么我会收到此错误消息 不支持 STA 线程上多个句柄的 WaitAll 我应该使用 STAThreadAttribute 属性吗 Update 不适用于 WPF 应用程序 笔记 错误位于 WaitHandle WaitAll doneE
  • std::map 只读操作的线程安全

    我有一个 std map 用于将值 字段 ID 映射到人类可读的字符串 当我的程序在任何其他线程启动之前启动时 该映射会被初始化一次 之后就不会再被修改 现在 我为每个线程提供了这个 相当大的 映射的自己的副本 但这显然是内存使用效率低下
  • 线程安全的get(访问器方法)

    我目前正在使用以下代码对变量进行线程安全访问 int gnVariable void getVariableValue int pnValue acquireLock Acquires the protection mechanism pn
  • Android:如何暂停和恢复可运行线程?

    我正在使用 postDelayed 可运行线程 当我按下按钮时 我需要暂停并恢复该线程 请任何人帮助我 这是我的主题 protected void animation music6 music4 postDelayed new Runnab
  • 我对线程失去了理智

    我想要这个类的对象 public class Chromosome implements Runnable Comparable

随机推荐