Aprove answer

You can’t call serialQueue.sync from the block that is being executed by the serialQueue.


Here is what I think is likely happening:

  1. You schedule a block A via serialQueue.async from notifyDelegate.
  2. In the context of block A execution, your delegate calls changeState, incorrectly assuming that current thread is not the serialQueue’s thread.
  3. From the changeState method, being on the serialQueue’s call stack, you schedule synchronously another block B via serialQueue.sync which can never start because you wait for it to be started in the previously asynchronously scheduled block A which is currently executed by the serialQueue.

Ways to avoid this situation:

  1. Never invoke public callbacks in the private serial queue that you use for synchronization.


  1. Don’t use private queue for synchronization, use os_unfair_lockor NSLock or NSRecursiveLock instead. It might also improve the performance.

Credit Goes to: stackoverflow.com

Related question with same questions but different answers