Protect state transitions with an `NSRecursiveLock`