Semaphore vs Dispatch Group

Batuhan Gobekli
3 min readJan 9, 2020
Photo by Jack Anstey on Unsplash

Grand Central Dispatch is one of those fundamental technologies all ios developers at least used one time of their lifetime. It’s basically scheduling and working tasks different queues and threads.

DispatchQueue.main.async { 
// Run async code on the main queue
}

We going to compare the common Foundation API’s DispatchSemaphore and DispatchGroup.

1. Dispatch

A dispatch group is a mechanism for monitoring a set of blocks. Your application can monitor the blocks in the group synchronously or asynchronously depending on your needs. By extension, a group can be useful for synchronizing for code that depends on the completion of other tasks.

Note that the blocks in a group may be run on different queues, and each individual block can add more blocks to the group.

The dispatch group keeps track of how many blocks are outstanding, and GCD retains the group until all its associated blocks complete execution.

Some tasks need group of subtasks to complete. For example, we need to log in before getting the users. So the dispatch group will handle the synchronize tasks. Rather than having to keep track of all the data sources ourselves, we can easily synchronize the work with a DispatchGroup.

Having dispatch groups also gives us a great benefit that our tasks will run in separate queues at the same time. This helps us to start quickly and then, if necessary, easily add competition later without having to rewrite any of our tasks. Just use enough to enter and leave functions

let dispatchGroup = DispatchGroup.init()

dispatchGroup.enter()
login {(data) in
//do stuff with the data that has been returned
dispatchGroup.leave()
}
dispatchGroup.enter()
getUsers {(data) in
//do stuff with the data that has been returned
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
//code to execute when all groups leave
}

2. Semaphore

A dispatch semaphore is an efficient implementation of a traditional counting semaphore. Dispatch semaphores call down to the kernel only when the calling thread needs to be blocked. If the calling semaphore does not need to block, no kernel call is made.

Like DispatchGroup, the semaphore API used to increment or decrement the counter by using wait() or signal() .Using wait() before signal() blocks/stops the queue until calling signal() .

Let’s create an example.

var semaphore = DispatchSemaphore(value: 0)getUsers { (data) in
//do stuff with the data that has been returned
semaphore.signal()
}
semaphore.wait(timeout: DispatchTime.distantFuture)

Conclusion

The same purpose is served by both DispachGroup and Semaphore.

You can use a semaphore to do the same thing as a set of dispatches, but it’s more common.

Dispatch groups are used when you have a lot of things that you want to do that can all happen at once, but you have to wait until they all finish before you do anything else. Dispatch groups are used when you have a lot of things to do that can all happen at once, but you have to wait until they all finish before you do anything else.

Semaphores can be used for the above, but they are synchronization objects of general use and can be used for many other purposes.

--

--