7

一位同事最近建议我使用 pthreads 而不是 GCD,因为它“更快”。我不同意它更快,但是pthreads 有什么风险?

我的感觉是,他们最终不会像 GCD 那样防白痴(而我的一个团队是 50% 的白痴)。pthreads很难正确吗?

4

4 回答 4

13

GCD 和 pthread 都是异步工作的方式,但它们有很大的不同。GCD 的大多数描述都是根据线程和线程池来描述的,但正如 DrPizza 所说

专注于 [线程和线程池] 就是错过重点。GCD 的价值不在于线程池,而在于队列
                                                                Win32 的 Grand Central Dispatch:为什么我想要它

与 pthread 等 API 相比,GCD 有一些不错的优势。

  • GCD 在鼓励和支持“并行海洋中的序列化孤岛”方面做了更多工作。GCD 可以很容易地避免大量的锁、互斥锁和条件变量,这些都是线程之间通信的正常方式。这是因为您将程序分解为任务,而 GCD 会在后台处理将任务输入和输出到适当的线程。因此,使用 GCD 进行编程可以让您几乎可以连续编写代码,而不必过多担心人们在线程代码中经常担心的事情。这使得代码更简单,更不容易出错。

  • GCD 可以为您进行扩展,因此程序使用的并行性与您将程序分解成的任务与硬件允许的依赖关系一样多。当然,将程序设计为可扩展的通常是困难的,但您仍然需要一些东西来实际利用这项工作以尽可能多地并行运行。像 GCD 这样的窃取调度程序的工作就完成了这部分工作。

  • GCD 是可组合的。如果您显式地为您想要异步或并行执行的操作生成线程,那么当您使用的库执行相同操作时,您可能会遇到问题。假设您决定可以同时运行八个线程,因为在给定程序运行的机器的情况下,这就是对您的程序有效的线程数。然后说你在每个线程上使用的库做同样的事情。现在您可以同时运行多达 64 个线程,这比您知道的对您的程序有效的多。

    线程池解决了这个问题,但每个人都需要使用相同的线程池。GCD 内部使用线程池,并为每个人提供相同的池。

  • GCD 提供了一堆“源”,使编写依赖于源或从源获取输入的事件驱动程序变得容易。例如,您可以非常轻松地设置一个队列,以在每次网络套接字上的数据可供读取时,或者当计时器触发时,或其他任何情况下启动任务。

于 2013-01-06T00:43:47.003 回答
10

我不认为他们很难做到正确,但是多年来使用了许多不同的方法(pthreads、GCD、NSThread、NSOperationQueue 等),我没有证据支持像“pthreads 更快”这样的断言。 " 即使它们更快(我希望差异充其量是微不足道的)我总是说,“使用完成工作的最高级别的抽象。” 此外,避免过早的优化。

有趣的是,GCD非常快。在我看来,可移植性是 pthread 相对于 GCD 的主要优势。如果这是 OSX/iOS 独有的代码,我认为使用 pthread 没有任何优势,相反没有经验证据。

于 2013-01-06T00:03:00.983 回答
3

忽略其他经过深思熟虑的技术原因,因为它们不相关。您不是为基准测试编写软件,是吗?在某些时候,用户会坐在您的设备前并尝试使用它。你知道如果你使用 pthreads 而不是 GCD 会发生什么吗?发生的情况是,您的软件在同时存在其他软件多任务处理的情况下无法很好地扩展,因为假设它是唯一同时运行的软件,它将争夺CPU 。这太疯狂了。没有人再运行单任务操作系统了。即使是单任务iOS 在后台运行很多东西。

相反,如果您运行的所有程序都使用 GCD,那么操作系统可以扩展在其队列上运行的并发任务的数量,从而更好地匹配实际处理器的数量,从而减少任务切换开销。

如果您的程序不需要伪实时低延迟,因此不需要一个专用线程来处理可用的东西(可能是您同事的“方式更快”的定义),那么 GCD 对用户来说很可能是优越的,因为它将更好地利用他们设备上的可用资源。即使 GCD 的 API 很糟糕或很慢,在其他不能跨不同进程扩展的解决方案上使用它也是值得的。

于 2014-03-20T09:01:51.317 回答
1

大概 NSThread 是使用 pthreads 库实现的,关键是一个概念的层次越低,你就越要做无用的重复性任务。

所以 pthreads 库并不难学,我在大学的教授教过它,即使是学习速度最慢的人(这么称呼他们)也能使用这个库,也许只是为了懒惰而随机复制粘贴代码但成功地完成了这项工作。

所以我绝对建议你实现一个 pthread 包装类,这很容易做到。

这样你就可以消除无用的东西,例如你可能会这样做一千次:

pthread_mutex_init( mutex_ptr, NULL);

所以(如果这是你的情况,但这只是一个例子)你可能总是传递 NULL,这对其他函数也是有效的。

一旦实现了这个类,就不能说它比 GCD 快。

GCD 做了一些优化,例如两个块可以在同一个线程中运行。

因此,我建议仅在比 GCD 快时才使用您定义的类,以使用时间分析器对其进行测试。

于 2013-01-06T00:09:25.430 回答