macos Grand Central Dispatch 与 NSThreads?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9238135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Grand Central Dispatch vs NSThreads?
提问by fdh
I searched a variety of sources but don't really understand the difference between using NSThreads
and GCD. I'm completely new to the OS X platform so I might be completely misinterpreting this.
我搜索了各种来源,但并没有真正理解 usingNSThreads
和 GCD之间的区别。我对 OS X 平台完全陌生,所以我可能完全误解了这一点。
From what I read online, GCD seems to do the exact same thing as basic threads (POSIX, NSThreads
etc.) while adding much more technical jargon ("blocks"). It seems to just overcomplicate the basic thread creation system (create thread, run function).
从我在网上阅读的内容来看,GCD 似乎与基本线程(POSIXNSThreads
等)做的完全相同,同时添加了更多技术术语(“块”)。它似乎只是使基本线程创建系统(创建线程、运行函数)过于复杂。
What exactly is GCD and why would it ever be preferred over traditional threading? When should traditional threads be used rather than GCD? And finally is there a reason for GCD's strange syntax? ("blocks" instead of simply calling functions).
GCD 到底是什么,为什么它比传统线程更受欢迎?什么时候应该使用传统线程而不是 GCD?最后还有 GCD 奇怪语法的原因吗?(“块”而不是简单地调用函数)。
I am on Mac OS X 10.6.8 Snow Leopard and I am not programming for iOS - I am programming for Macs. I am using Xcode 3.6.8 in Cocoa, creating a GUI application.
我在 Mac OS X 10.6.8 Snow Leopard 上,我不是为 iOS 编程 - 我是为 Mac 编程。我在 Cocoa 中使用 Xcode 3.6.8,创建了一个 GUI 应用程序。
回答by Dan Rosenstark
Advantages of Dispatch
派遣的优势
The advantages of dispatch are mostly outlined here:
调度的优点主要在这里概述:
The idea is that you eliminate work on your part, since the paradigm fits MOST code more easily.
这个想法是你消除了你的工作,因为范式更容易适应大多数代码。
- It reduces the memory penalty your application pays for storing thread stacks in the application's memory space.
- It eliminates the code needed to create and configure your threads.
- It eliminates the code needed to manage and schedule work on threads.
- It simplifies the code you have to write.
- 它减少了您的应用程序为在应用程序的内存空间中存储线程堆栈而支付的内存损失。
- 它消除了创建和配置线程所需的代码。
- 它消除了管理和调度线程工作所需的代码。
- 它简化了您必须编写的代码。
Empirically, using GCD-type locking instead of @synchronized
is about 80% faster or more, though micro-benchmarks may be deceiving. Read more here, though I think the advice to go async with writes does not apply in many cases, and it's slower (but it's asynchronous).
从经验上看,使用 GCD 类型的锁定而不是@synchronized
大约 80% 或更多,尽管微基准可能具有欺骗性。在这里阅读更多,虽然我认为异步写入的建议在许多情况下并不适用,而且速度较慢(但它是异步的)。
Advantages of Threads
线程的优势
Why would you continue to use Threads? From the same document:
你为什么要继续使用线程?来自同一份文件:
It is important to remember that queues are not a panacea for replacing threads. The asynchronous programming model offered by queues is appropriate in situations where latency is not an issue. Even though queues offer ways to configure the execution priority of tasks in the queue, higher execution priorities do not guarantee the execution of tasks at specific times. Therefore, threads are still a more appropriate choice in cases where you need minimal latency, such as in audio and video playback.
重要的是要记住,队列不是替换线程的灵丹妙药。队列提供的异步编程模型适用于延迟不成问题的情况。尽管队列提供了配置队列中任务执行优先级的方法,但更高的执行优先级并不能保证任务在特定时间执行。因此,在需要最小延迟的情况下,例如在音频和视频播放中,线程仍然是更合适的选择。
Another place where I haven't personally found an ideal solution using queues is daemon processes that need to be constantly rescheduled. Not that you cannot reschedule them, but looping within a NSThread method is simpler (I think). Edit:Now I'm convinced that even in this context, GCD-style locking would be faster, and you could also do a loop within a GCD-dispatched operation.
我个人还没有找到使用队列的理想解决方案的另一个地方是需要不断重新调度的守护进程。并不是说您不能重新安排它们,而是在 NSThread 方法中循环更简单(我认为)。编辑:现在我确信即使在这种情况下,GCD 样式的锁定也会更快,并且您还可以在 GCD 调度的操作中执行循环。
Blocks in Objective-C?
Objective-C 中的块?
Blocks are really horrible in Objective-C due to the awful syntax (though Xcode can sometimes help with autocompletion, at least). If you look at blocks in Ruby (or any other language, pretty much) you'll see how simple and elegant they are for dispatching operations. I'd say that you'll get used to the Objective-C syntax, but I really think that you'll get used to copying from your examples a lot :)
由于糟糕的语法,Objective-C 中的块真的很糟糕(尽管 Xcode 有时可以帮助自动完成,至少)。如果您查看 Ruby(或几乎任何其他语言)中的块,您会发现它们用于调度操作是多么简单和优雅。我会说你会习惯 Objective-C 语法,但我真的认为你会习惯从你的例子中复制很多:)
You might find my examples from hereto be helpful, or just distracting. Not sure.
你可能会发现我这里的例子很有帮助,或者只是分散注意力。不确定。
回答by Grzegorz Adam Hankiewicz
While the answers so far are about the context of threads vs GCD inside the domain of a single application and the differences it has for programming, the reason you should always prefer GCD is because of multitasking environments (since you are on MacOSX and not iOS). Threads are ok if your application is running aloneon your machine. Say, you have a video edition program and want to apply some effect to the video. The render is going to take 10 minutes on a machine with eight cores. Fine.
虽然到目前为止的答案是关于单个应用程序域内的线程与 GCD 的上下文以及它在编程方面的差异,但您应该始终选择 GCD 的原因是因为多任务环境(因为您使用的是 MacOSX 而不是 iOS) . 如果您的应用程序在您的机器上单独运行,线程就可以了。假设您有一个视频编辑程序,并且想要对视频应用一些效果。在具有 8 个内核的机器上渲染将需要 10 分钟。美好的。
Now, while the video app is churning in the background, you open an image edition program and play with some high resolution image, decide to apply some special image filter and your image application being clever detects you have eight cores and starts eight threads to process the image. Nice isn't it? Except that's terrible for performance. The image edition app doesn't know anything about the video app (and vice versa) and therefore both will request their respectively optimum number of threads. And there will be pain and blood while the cores try to switch from one thread to another, because to avoid starvation the CPU will eventually let all threads run, even though in this situation it would be more optimal to run only 4 threads for the video app and 4 threads for the image app.
现在,当视频应用程序在后台运行时,您打开一个图像编辑程序并播放一些高分辨率图像,决定应用一些特殊的图像过滤器,并且您的图像应用程序很聪明地检测到您有八个内核并启动八个线程来处理图片。不错吧?除了这对性能来说很糟糕。图像编辑应用程序对视频应用程序一无所知(反之亦然),因此两者都会请求各自的最佳线程数。并且当内核尝试从一个线程切换到另一个线程时会感到痛苦和血腥,因为为了避免饥饿,CPU 最终会让所有线程运行,即使在这种情况下,最好只为视频运行 4 个线程应用程序和图像应用程序的 4 个线程。
For a more detailed reference, take a look at http://deusty.blogspot.com/2010/11/introducing-gcd-based-cocoahttpserver.htmlwhere you can see a benchmark of an HTTP server using GCD versus thread, and see how it scales. Once you understand the problem threads have for multicore machines in multi-app environments, you will always want to use GCD, simply because threads are not always optimal, while GCD potentially can be since the OS can scale thread usage per app depending on load.
有关更详细的参考,请查看http://deusty.blogspot.com/2010/11/introducing-gcd-based-cocoahttpserver.html,您可以在其中查看使用 GCD 与线程的 HTTP 服务器的基准测试,并参见它是如何扩展的。一旦您了解了多应用程序环境中多核机器的线程问题,您将始终希望使用 GCD,因为线程并不总是最佳的,而 GCD 可能是最佳的,因为操作系统可以根据负载扩展每个应用程序的线程使用量。
Please, remember we won't have more GHz in our machines any time soon. From now on we will only have more cores, so it's your duty to use the best tool for this environment, and that is GCD.
请记住,我们的机器很快就不会再有更多的 GHz 了。从现在开始,我们只会有更多的内核,所以你有责任为这个环境使用最好的工具,那就是 GCD。
回答by bryanmac
Blocks allow for passing a block of code to execute. Once you get past the "strange syntax", they are quite powerful.
块允许传递要执行的代码块。一旦你克服了“奇怪的语法”,它们就会非常强大。
GCD also uses queues which if used properly can help with lock free concurrency if the code executing in the separate queues are isolated. It's a simpler way to offer background and concurrency while minimizing the chance for deadlocks (if used right).
GCD 还使用队列,如果使用得当,如果在单独队列中执行的代码是隔离的,则可以帮助实现无锁并发。这是一种更简单的方式来提供后台和并发性,同时最大限度地减少死锁的机会(如果使用得当)。
The "strange syntax" is because they chose the caret (^) because it was one of the few symbols that wasn't overloaded as an operator in C++
“奇怪的语法”是因为他们选择了插入符号 (^),因为它是少数没有在 C++ 中作为运算符重载的符号之一
请参阅:https: //developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
When it comes to adding concurrency to an application, dispatch queues provide several advantages over threads. The most direct advantage is the simplicity of the work-queue programming model. With threads, you have to write code both for the work you want to perform and for the creation and management of the threads themselves. Dispatch queues let you focus on the work you actually want to perform without having to worry about the thread creation and management. Instead, the system handles all of the thread creation and management for you. The advantage is that the system is able to manage threads much more efficiently than any single application ever could. The system can scale the number of threads dynamically based on the available resources and current system conditions. In addition, the system is usually able to start running your task more quickly than you could if you created the thread yourself.
Although you might think rewriting your code for dispatch queues would be difficult, it is often easier to write code for dispatch queues than it is to write code for threads. The key to writing your code is to design tasks that are self-contained and able to run asynchronously. (This is actually true for both threads and dispatch queues.)
...
Although you would be right to point out that two tasks running in a serial queue do not run concurrently, you have to remember that if two threads take a lock at the same time, any concurrency offered by the threads is lost or significantly reduced. More importantly, the threaded model requires the creation of two threads, which take up both kernel and user-space memory. Dispatch queues do not pay the same memory penalty for their threads, and the threads they do use are kept busy and not blocked.
在向应用程序添加并发性时,调度队列比线程提供了几个优势。最直接的优点是工作队列编程模型的简单性。对于线程,您必须为要执行的工作以及线程本身的创建和管理编写代码。调度队列让你专注于你真正想要执行的工作,而不必担心线程的创建和管理。相反,系统会为您处理所有线程的创建和管理。优点是系统能够比任何单个应用程序更有效地管理线程。系统可以根据可用资源和当前系统条件动态调整线程数量。此外,
尽管您可能认为为调度队列重写代码会很困难,但为调度队列编写代码通常比为线程编写代码更容易。编写代码的关键是设计自包含且能够异步运行的任务。(实际上对于线程和调度队列都是如此。)
...
虽然您指出在串行队列中运行的两个任务不会同时运行是正确的,但您必须记住,如果两个线程同时获取锁,线程提供的任何并发性都会丢失或显着减少。更重要的是,线程模型需要创建两个线程,它们占用内核空间和用户空间内存。调度队列不会为它们的线程支付相同的内存损失,并且它们确实使用的线程保持忙碌而不被阻塞。
回答by Alok
GCD (Grand Central Dispatch): GCD provides and manages FIFO queues to which your application can submit tasks in the form of block objects. Work submitted to dispatch queues are executed on a pool of threads fully managed by the system. No guarantee is made as to the thread on which a task executes. Why GCD over threads :
GCD(Grand Central Dispatch):GCD 提供并管理 FIFO 队列,您的应用程序可以以块对象的形式向其提交任务。提交到调度队列的工作在由系统完全管理的线程池中执行。不保证任务在哪个线程上执行。为什么 GCD 超过线程:
How much work your CPU cores are doing How many CPU cores you have. How much threads should be spawned. If GCD needs it can go down into the kernel and communicate about resources, thus better scheduling. Less load on kernel and better sync with OS GCD uses existing threads from thread pool instead of creating and then destroying. Best advantage of the system's hardware resources, while allowing the operating system to balance the load of all the programs currently running along with considerations like heating and battery life.
你的 CPU 内核做了多少工作 你有多少 CPU 内核。应该产生多少线程。如果 GCD 需要,它可以进入内核并就资源进行通信,从而更好地进行调度。减少内核负载并更好地与操作系统同步 GCD 使用线程池中的现有线程,而不是创建然后销毁。系统硬件资源的最佳优势,同时允许操作系统平衡当前运行的所有程序的负载以及加热和电池寿命等考虑因素。
I have shared my experience with threads, operating system and GCD AT http://iosdose.com
我在http://iosdose.com 上分享了我在线程、操作系统和 GCD 方面的经验