NSLock.lock() выполняется, пока блокировка уже удерживается?

Я рассматриваю пример кода Retrier Alamofire:

   func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
        lock.lock() ; defer { lock.unlock() }

        if let response = request.task.response as? HTTPURLResponse, response.statusCode == 401 {
            requestsToRetry.append(completion)

            if !isRefreshing {
                refreshTokens { [weak self] succeeded, accessToken, refreshToken in
                    guard let strongSelf = self else { return }

                    strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }

                    ...
                }
            }
        } else {
            completion(false, 0.0)
        }
    }

Я не понимаю, как вы можете иметь lock.lock() в первой строке функции, а затем также имеют ту же строку strongSelf.lock.lock() в закрытии передается refreshTokens,

Если первая блокировка не снята до конца should метод, когда defer разблокировка выполняется как вторая strongSelf.lock.lock() успешно выполнить, пока удерживается первая блокировка?

1 ответ

Решение

Завершающее закрытие refreshTokensгде этот второй вызов lock()/unlock() называется, работает асинхронно. Это потому, что закрытие @escaping и вызывается изнутри responseJSON внутри refreshTokens рутина. Итак should метод выполнил отложенный unlock к моменту закрытия refreshTokens на самом деле называется.

Сказав это, это не самый элегантный код, который я когда-либо видел, где полезность блокировки неясна, а риск взаимоблокировки так зависит от деталей реализации других подпрограмм. Похоже, здесь все в порядке, но я не виню вас за то, что вы подняли бровь.

Другие вопросы по тегам