How to avoid Thread Explosion and Deadlock with GCD in Swift?

Note: If you are a beginner and you find it difficult to understand things written in this article. Feel free to ask questions on my Reddit page or Twitter.

To Read, How to use GCD (Grand Central Dispatch) in Swift? - Synchronous & Asynchronous Programming Tutorial. Click Here.

To Read, Difference between Concurrent Queue and Serial Queue. Click Here.

To Read, How to group dispatch queues in Swift? Click Here.

To Read, What is QoS (Quality of Service) in GCD? Click Here.

To Read, What is a DispatchWorkItem in GCD (Grand Central Dispatch)? - Swift, Click Here.

Remember, you can do it. 😉


If you are not aware of this term Thread Explosion and Deadlock, let me tell you, it’s a nightmare for an iOS Developer.

But, it’s not so difficult to avoid this. It is crucial to use GCD with Caution.

How to avoid Thread Explosion and Deadlock?

Before we get into the solution, we need to understand the reason for Thread Explosion and Deadlock.

You need to understand that Threads aren’t cheap, whenever you try to submit a thread, your core is getting utilized. Thread explosions and Deadlock are generally caused when you try to submit too many tasks to a concurrent queue which is blocked due to reasons like sync operations, or all the cores are in use.

When all the cores are busy, and another thread is now waiting for its execution, GCD tries to open a new thread on another core, and that is how you face Thread Explosions and Deadlock.

Note: Always update your UI in an async task. Use OperationQueues as it provides maxConcurrentOperationCount. Keep a tab on how many tasks you are submitting to the queue.

Now let’s see an example of a thread explosion. 🙊

// Create Concurrent Queue
let queue = DispatchQueue(label: "com.swiftpal.dispatch.explosion", attributes: .concurrent)

for i in 0 ... 1000 {
    // Async Tasks
    queue.async {
        Thread.sleep(forTimeInterval: 1)
        print("Executed Task \(i)")
    }
}

// Sync Task
DispatchQueue.main.sync {
    print("All Tasks Completed")
}

This code may lead to Thread Explosion. Never make the mistake I have done above.

We should always limit our tasks, and we can achieve this with DispatchSemaphore.

What is DispatchSemaphore?

DispatchSemaphore is used to count semaphore. By calling the signal() function, we can increase its count, and by calling the wait() function, we can decrease its count.

Now let's see how DispatchSemaphore can help us avoid the explosion.

// Define number of tasks
let concurrentTasks = 4

// Create Concurrent Queue
let queue = DispatchQueue(label: "com.swiftpal.dispatch.explosion", attributes: .concurrent)

// Create Semaphore object
let semaphore = DispatchSemaphore(value: concurrentTasks)

for i in 0 ... 1000 {
    // Async Tasks
    queue.async {
        Thread.sleep(forTimeInterval: 1)
        print("Executed Task \(i)")
        semaphore.signal()   // Sema Count Increased
    }
    semaphore.wait() // Sema Count Decreased
}

// Async Task
DispatchQueue.main.async {
    print("All Tasks Completed")
}

/* Output:
.....
 Executed Task 997
 All Tasks Completed
 Executed Task 998
 Executed Task 999
 Executed Task 1000
 */

You can see that we have added a variable name concurrentTasks, which is passed into the DispatchSemaphore object to set a maximum number of concurrent tasks to be executed at a time.

Next, our semaphore object increases its value in the async task and then decreases its value after the block.

I also changed the sync task, which was executing on the main thread to an async task.

If you run this code in the playground, your output should match the output shown in the code above. And as the queue we created is concurrent, the “All Tasks Completed” is printed earlier than the last there tasks.

As you can see, with the help of semaphore, only four concurrent tasks can be executed at a given time.

Four may seem less to you. But it’s a good number in terms of tasks getting executed at a time.

I hope you liked reading my article. Next, we will be exploring OperationQueues, so subscribe to stay updated about my upcoming articles.

If you have any suggestions or questions, Feel free to connect me on Twitter. 😉

Combine Framework Beginner Tutorial in Swift - Working with NotificationCenter

What is a DispatchWorkItem in GCD (Grand Central Dispatch)? - Swift