风险评估:使用Pthreads(与GCD或NSThread相比)

时间:2013-01-05 23:45:05

标签: objective-c pthreads grand-central-dispatch nsthread

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

我的感觉是,他们最终不会像GCD一样笨拙(我的团队中有50%是白痴)。 pthreads很难做对吗?

4 个答案:

答案 0 :(得分:13)

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

  

专注于[线程和线程池]是错过了重点。 GCD的价值不在于线程池,而在于排队   Grand Central Dispatch for Win32: why I want it

与pthreads等API相比,GCD有一些很好的优势。

  • GCD在鼓励和支持“并行海洋中的序列化孤岛”方面做得更多。 GCD可以很容易地避免大量的锁和互斥锁以及条件变量,这些是线程之间通信的正常方式。这是因为您将程序分解为任务,GCD处理任务输入并输出到后台的相应线程。因此,使用GCD进行编程可以让您完全按顺序编写,而不必担心人们经常在线程代码中担心的问题。这使代码更简单,更容易出错。

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

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

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

  • GCD提供了大量“来源”,可以轻松编写依赖于源或从源获取输入的事件驱动程序。例如,每当数据可用于在网络套接字上读取时,或者当计时器触发时,您都可以非常轻松地设置队列以启动任务。

答案 1 :(得分:10)

我不认为他们很难做对,但多年来一直使用许多不同的方法(pthreads,GCD,NSThread,NSOperationQueue等)我有 no 证据支持像“pthreads更快”这样的断言。即使它们更快(我希望差异最小),我总是说,“使用最高级别的抽象来完成工作。”此外,避免过早优化。

有趣地说,GCD非常快。我怎么看,可移植性是pthreads优于GCD的主要优势。如果这是OSX / iOS独家代码,我认为使用pthreads没有任何优势,缺乏相反的经验证据。

答案 2 :(得分:3)

忽略其他经过深思熟虑的技术原因,因为它们并不相关。您不是为基准编写软件,是吗?在某些时候,用户将坐在您的设备前面并尝试使用它。你知道如果使用pthreads而不是GCD会发生什么?会发生什么your software doesn't scale well in the presence of other software multitasking at the same time,因为它假设它是同时运行的唯一软件,它将战斗。哪个是疯了。没有人再运行单任务操作系统了。即使是单一任务 iOS也会在后台运行很多东西。

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

如果你的程序不需要伪实时低延迟,那么就会有一个专门的线程来处理它的东西(可能是你的同事的定义" 方式更快"),GCD可能会对用户更有优势,因为它将更好地利用其设备上的可用资源。即使GCD的API很糟糕或很慢,但将其用于其他不能在不同流程中扩展的解决方案也是值得的。

答案 3 :(得分:1)

可能NSThread是使用pthreads库实现的,关键是概念的级别越低,你就越需要完成无用和重复的任务。

所以pthreads库并不是那么难学,我大学的教授教它,甚至最多(称之为'em')学习的人也很慢,可以使用这个库,可能是随机复制粘贴代码懒惰,但成功地完成了工作。

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

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

pthread_mutex_init( mutex_ptr, NULL);

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

一旦实现了类,就不会说它比GCD更快。

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

所以我建议只在比GCD更快的情况下使用你定义的类,用时间分析器测试它。