42

I'm writing a moderately complex iOS program that needs to have multiple threads for some of its longer operations (parsing, connections to the network...etc). However, I'm confused as to what the difference is between dispatch_get_global_queue and dispatch_queue_create.

Which one should I use and could you give me a simple explanation of what the difference is in general? Thanks.

James Webster
  • 31,873
  • 11
  • 70
  • 114
Nosrettap
  • 10,940
  • 23
  • 85
  • 140

3 Answers3

71

As the documentation describes, a global queue is good for concurrent tasks (i.e. you're going to dispatch various tasks asynchronously and you're perfectly happy if they run concurrently) and if you don't want to encounter the theoretical overhead of creating and destroying your own queue.

The creating of your own queue is very useful if you need a serial queue (i.e. you need the dispatched blocks to be executed one at a time). This can be useful in many scenarios, such as when each task is dependent upon the preceding one or when coordinating interaction with some shared resource from multiple threads.

Less common, but you will also want to create your own queue if you need to use barriers in conjunction with a concurrent queue. In that scenario, create a concurrent queue (i.e. dispatch_queue_create with the DISPATCH_QUEUE_CONCURRENT option) and use the barriers in conjunction with that queue. You should never use barriers on global queues.

My general counsel is if you need a serial queue (or need to use barriers), then create a queue. If you don't, go ahead and use the global queue and bypass the overhead of creating your own.


If you want a concurrent queue, but want to control how many operations can run concurrently, you can also consider using NSOperationQueue which has a maxConcurrentOperationCount property. This can be useful when doing network operations and you don't want too many concurrent requests being submitted to your server.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 2
    Though note that in Lion it's now possible to get a concurrent queue from `dispatch_queue_create()` by passing `DISPATCH_QUEUE_CONCURRENT`. It's not specified (and probably doesn't matter) whether this will just return one of the existing global queues. – jscs Jun 11 '12 at 18:59
  • 1
    I should have added, "presumably that functionality will be coming to iOS eventually". – jscs Jun 11 '12 at 19:13
  • 1
    Upvoted for correctly pointed out the differences in term of concurrent and serial queues. – user523234 Jun 11 '12 at 22:34
  • A small note in reply to [my own comment](http://stackoverflow.com/questions/10984885/what-is-the-difference-between-dispatch-get-global-queue-and-dispatch-queue-crea/10985701#comment14350505_10985701) above: the `DISPATCH_QUEUE_CONCURRENT` must, in fact, create a new queue, because it's possible to use dispatch barriers on such a queue, which is not allowed with the global queues. – jscs Aug 13 '12 at 21:44
  • About the diff of 'mainQueue vs. anyOthercreatedSerialQueue'. While both are serial, mainQueue is to be used for UI related tasks or basically anything important that is to be returned immediately( though I can't think of something good now). But *anyOthercreatedSerialQueue* is to be used for special serialization of something you might have to do in a background thread such as writing to an array as you already presented in your answer [here](https://stackoverflow.com/questions/28784507/adding-items-to-swift-array-across-multiple-threads-causing-issues-because-arra?rq=1) – mfaani Dec 27 '16 at 16:42
42

Just posted in a different answer, but here is something I wrote quite a while back:

The best way to conceptualize queues is to first realize that at the very low-level, there are only two types of queues: serial and concurrent.

Serial queues are monogamous, but uncommitted. If you give a bunch of tasks to each serial queue, it will run them one at a time, using only one thread at a time. The uncommitted aspect is that serial queues may switch to a different thread between tasks. Serial queues always wait for a task to finish before going to the next one. Thus tasks are completed in FIFO order. You can make as many serial queues as you need with dispatch_queue_create.

The main queue is a special serial queue. Unlike other serial queues, which are uncommitted, in that they are "dating" many threads but only one at time, the main queue is "married" to the main thread and all tasks are performed on it. Jobs on the main queue need to behave nicely with the runloop so that small operations don't block the UI and other important bits. Like all serial queues, tasks are completed in FIFO order.

If serial queues are monogamous, then concurrent queues are promiscuous. They will submit tasks to any available thread or even make new threads depending on system load. They may perform multiple tasks simultaneously on different threads. It's important that tasks submitted to the global queue are thread-safe and minimize side-effects. Tasks are submitted for execution in FIFO order, but order of completion is not guaranteed. As of this writing, there are only three concurrent queues and you can't make them, you can only fetch them with dispatch_get_global_queue.

edit: blog post expanding on this answer: http://amattn.com/p/grand_central_dispatch_gcd_summary_syntax_best_practices.html

amattn
  • 10,045
  • 1
  • 36
  • 33
  • 1
    The blog post link is dead. – bradley.ayers Jan 21 '14 at 09:46
  • Still seems to work for me. I did recently update blog engines, so there is a new canonical address here: http://amattn.com/p/grand_central_dispatch_gcd_summary_syntax_best_practices.html – amattn Feb 27 '14 at 18:15
  • and wrong... From my experience, this answer is not accurate. User queue can be created (and function) as a concurrent queue. @PaulRobinson – Guy Oct 11 '14 at 13:26
  • 1
    From Apple's dispatch_queue_create documentation: In OS X v10.7 and later or iOS 4.3 and later, specify DISPATCH_QUEUE_SERIAL (or NULL) to create a serial queue or specify DISPATCH_QUEUE_CONCURRENT to create a concurrent queue. In earlier versions, you must specify NULL for this parameter. – Carl Smith Jun 09 '15 at 23:16
0

One returns the existing global queue, the other creates a new one. Instead of using GCD, I would consider using NSOperation and operation queue. You can find more information about it in this guide. Typically, of you want the operations to execute concurrently, you want to create your own queue and put your operations in it.

Max Yankov
  • 12,551
  • 12
  • 67
  • 135
  • Just to clarify, if you're creating a dispatch queue, it's serial. If you're using the global dispatch queue, it can be concurrent (but not guaranteed to be so). I assume your counsel re creating queues for concurrency is related to operation queues, not dispatch queues. (I know you know that, but I just wanted to make sure readers weren't confused.) – Rob Jun 11 '12 at 18:47
  • 1
    Yes, I'm talking about operation queues. I was facing the same problem some time ago, and when I created my own operation queue without any further configuration, operations added in it were executed concurrently to one another. – Max Yankov Jun 11 '12 at 18:49