2

What is the difference (advantage and disadvantage) between using DispatchGroup and NSRecursiveLock?

It looks like they are doing exactly the same thing.

Dmitry
  • 527
  • 5
  • 13
  • See https://stackoverflow.com/questions/35906568/wait-until-swift-for-loop-with-asynchronous-network-requests-finishes-executing and then decide if NSLock does the same thing. – rmaddy Sep 25 '19 at 20:52
  • Possible duplicate of [How to utilize NSLock to prevent a function from firing twice?](https://stackoverflow.com/questions/45202663/how-to-utilize-nslock-to-prevent-a-function-from-firing-twice) – Shehata Gamal Sep 25 '19 at 20:53

2 Answers2

4

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.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • FYI, I didn’t delve into the `NSLock` (the original question) vs `NSRecursiveLock` distinction, as it doesn’t seem relevant in the discussion of locks vs groups. The difference between these two types of locks is that one allows a given thread to recursively lock, whereas the other doesn’t. But from the perspective of inter-thread coordination, they’re functionally the same. But if you have some question specific to the recursive locks as opposed to non-recursive ones, let me know. – Rob Sep 26 '19 at 15:59
  • 1
    At the risk of being perceived as a troll: Don't use recursive locks. They're an anti-pattern. :) – ipmcc Sep 27 '19 at 16:13
  • 1
    @ipmcc - No worries. I’m not advocating recursive locks, but just clarifying why I avoided them in my answer. But the question was explicitly changed from `NSLock` to `NSRecursiveLock` for some reason, possibly in response to your “or even the same thread” asides. (BTW, Dimitry, it is inappropriate to change question in such a way it invalidates existing answers.) Re correctness of recursive locks, they’re not anti-pattern, IMHO, as they are the right tool for in certain, narrow cases, but, yes, they can be misused as kludgy work-arounds to sloppy lock code, and as such, are often code smell. – Rob Sep 27 '19 at 16:37
1

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.

ipmcc
  • 29,581
  • 5
  • 84
  • 147