Dispatch and global queues

Dispatch queues are FIFO queues to which your application can submit tasks in the form of block objects. Dispatch queues execute tasks either serially or concurrently. Work submitted to dispatch queues executes on a pool of threads managed by the system. Except for the dispatch queue representing your app’s main thread, the system makes no guarantees about which thread it uses to execute a task.

You schedule work items synchronously or asynchronously. When you schedule a work item synchronously, your code waits until that item finishes execution. When you schedule a work item asynchronously, your code continues executing while the work item runs elsewhere.

print("a")
DispatchQueue.main.async {
	print("b")
	
	DispatchQueue.main.async {
        print("c")
    
        DispatchQueue.main.async {
            print("d")

            DispatchQueue.main.sync {
                print("e")
            }
        }
    }
	
	DispatchQueue.global().sync {
        print("f")
		
        DispatchQueue.main.sync {
            print("g")
        }
    }
	
	print("h")
}
print("i")

Ever wondered what the above code prints. If you said,
a
i
b
f
Then you know whats going on here. Actually if you run it in a real world scenario, the app will crash. I was using the swift playground, so it didn’t crash for me.

Let me explain. Firstly, a gets printed. This is easy. Next, we enter the background phase and the code is asynchronous. We move out of the scope and print i. This is in the main loop. Then we print b, which is waiting in the background. It’s easy until now.

Next we make another dispatch call, and it goes into the background. Therefore we call the dispatch queue on the global queue and synchronously print f.

Then we make a call to DispatchQueue.main.sync and try to print g. This ain’t going to work. Because the main thread is waiting on the background queue to finish. Since both are in sync, we end up waiting for each other and we have a deadlock. And your app ends up crashing.

Now let’s try fixing this. The simple fix is making the call to print g async, so that instead of the main thread waiting for the global queue to finish, we send it to the background and make it asynchronous.

 DispatchQueue.main.async {
            print("g")
        }

This will fix the issue.

Leave a Reply

Your email address will not be published. Required fields are marked *