33

I am trying to create a (network) synchronized array for the company I work for. While the networking part works fine, I have dwelled into an issue.

My wish was to create a new queue using dispatch_create_queue, to which I would add two blocks that are not to run on the main thread, but in a serial manner, meaning that first the first block has to run, then the second, and never in parallel.

I've read the apple documentation, but it is confusing to say the least.

  • When I create my queue using dispatch_queue_create and then add the blocks (after they have been defined) using dispatch_sync, I have found out that the block is still executing on the main thread.

  • When using dispatch_async, thats when the blocks are not executing on the main thread.

  • When I try to add both blocks using dispatch_sync They get blocked forever.

  • The only time that both blocks seem to run fine and off the main thread is when calling dispatch_async.

However the reason why I chose GCD and the sync method so that I was under the impression that I was creating a new queue (and thus a new thread) and that adding blocks to that queue would simply block one until the other had finished executing. Is this not the case, or does creating a queue does not guarantee that the code will not run on the main thread ?

Mazyod
  • 22,319
  • 10
  • 92
  • 157
Ælex
  • 14,432
  • 20
  • 88
  • 129

1 Answers1

66

This is a FIFO queue in GCD:

dispatch_queue_t serialQueue = dispatch_queue_create("com.blah.queue", DISPATCH_QUEUE_SERIAL);

...
dispatch_async(serialQueue, ^{
    //block1
});

dispatch_async(serialQueue, ^{
    //block2
});
Fernando Mazzon
  • 3,562
  • 1
  • 19
  • 21
  • So it has nothing to do with dispatch_sync then ? Only the flag used when creating it? – Ælex Jan 02 '13 at 20:41
  • 5
    The dispatch_async makes it so that the dispatch call itself doesn't block until the block is finished. If you use dispatch_sync, the task itself is executed in whatever thread the queue is in, but you block the current thread until the task is done. I don't think that's what you need. – Fernando Mazzon Jan 02 '13 at 20:43
  • Thank you, those api names are a bit confusing. Saved my day ! :) – Ælex Jan 02 '13 at 20:43
  • @Joe: `dispatch_async()` doesn't really mean "run in the background", it just means "don't wait for this to run". (There's also no guarantees made by GCD for thread/queue correspondance other than that the main queue is on the main thread.) – jscs Jan 02 '13 at 20:49
  • 3
    All dispatch queues are FIFO. Meaning that as long as you reuse the same queue, the order of block execution is determined and guaranteed not to lock and is thus thread-safe. – jmstone617 Jan 02 '13 at 22:20
  • @jmstone: You mean all serial dispatch queues are FIFO. For concurrent queues, you should assume that all blocks are executing in parallel. – gnasher729 Feb 18 '15 at 22:38
  • 1
    @gnasher729 Even concurrent queues are technically FIFO. From Apple's documentation on concurrent queues: "Concurrent queues (also known as a type of global dispatch queue) execute one or more tasks concurrently, but tasks are still started in the order in which they were added to the queue." – jmstone617 Feb 18 '15 at 23:21
  • 1
    @jmstone Wouldn't a concurrent queue be first in only? Since they are running in parallel you have no guarantee that the first job in will be the first job out? I've experienced this with making calls to Google's GeoCode API, where I've sent a series of queries that were stored in an array (addresses) and the returned JSON does not come back in the same order that I sent. I.E. Send Address1, Address2, Address3 in that order and the location data returned could be Location 2, Location 1, Location 3... – PruitIgoe May 11 '16 at 11:28
  • 4
    @PruitIgoe FIFO does not mean FIFC (first in first to complete). Like I mentioned above, the FIFO order just guarantees that tasks are started in the order they were added to the queue. That doesn't mean they FINISH in the same order, as evidenced by the example you gave. – jmstone617 May 26 '16 at 03:23
  • What if I have dynamic count of tasks, can I use for loop for execution? – iDevAmit Jun 02 '17 at 06:41
  • 1
    @jmstone617 oh god dammit, I had a case in which a seemingly serial queue was somehow allowing for multiple concurrency despite the flags I set. Went here and then read your comment to this answer talking about how important it is to ACTUALLY use the same DispatchQueue object to push work items into async. AKA 2 DispatchQueues with same labels are not equal. Thank you for your brief tip – Isaaс Weisberg Apr 14 '19 at 15:21
  • FIFO stands for First In First Out. "First in" refers to first queued, "first out" refers to first out of the queue and to begin execution. What happens after that is no longer the queues domain. Hence the question demands for a serial queue, that will not start execution of the second task, until the first one is done. – Conor Dec 09 '21 at 10:46