What is the difference (advantage and disadvantage) between using DispatchGroup and NSRecursiveLock?
It looks like they are doing exactly the same thing.
What is the difference (advantage and disadvantage) between using DispatchGroup and NSRecursiveLock?
It looks like they are doing exactly the same thing.
Locks and groups serve very different purposes. When dealing with a series of concurrent tasks:
A lock generally is used to prevent/block these tasks from simultaneously interacting with some shared, non thread-safe, resource.
A group is generally used for identifying when these concurrent tasks are all complete (regardless of the order in which they finished).
For example, if processing a series of images in parallel, you might use a lock or similar mechanism to update some property (e.g. the array of the results), whereas the dispatch groups is used to know when all of these concurrent tasks are done.
The primary difference is that DispatchGroup is closer to a counting semaphore with a callback, whereas an NSLock is a simple mutex.
For instance, a DispatchGroup can be entered more than once, by one or more threads, and entering a DispatchGroup will never block the calling thread. The calling threads are also responsible for balancing each enter call with a call to leave. If there is a notify callback registered on the group, it will execute once the number of enters minus the number of leaves reaches 0. A good example of using a DispatchGroup would be to make multiple network requests and have a single piece of callback code be executed after all the network requests have completed (or timed out, etc).
However, if one thread locks an NSLock, any other thread (or even the same thread, for that matter) tries to lock it again before it is unlocked, the second thread will be blocked until it is unlocked (and possibly never, if you try to lock it twice from the same thread). A good example of using an NSLock is to provide multi-threaded access to a single, mutable piece of data. In this case, multiple threads can be sure to get coherent reads and writes to/from the mutable storage without potentially trampling one another.
NSLock (and mutexes in general) are a much lower level synchronization primitive than a DispatchGroup. In general, you should always use the highest level primitive that achieves your goal. If a DispatchGroup will do the job, use it, and ignore NSLock.