NSLock.lock() 在锁已持有的情况下执行?
NSLock.lock() executed while lock already held?
我正在审查一些 Alamofire sample Retrier 代码:
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()
,然后在传递给 refreshTokens
的闭包中也使用相同的行 strongSelf.lock.lock()
。
如果执行defer
解锁时第一个锁直到should
方法结束才释放,那么第二个strongSelf.lock.lock()
如何在第一个锁成功执行的同时执行举办了吗?
refreshTokens
的尾随闭包,其中调用了对 lock()
/unlock()
的第二次调用,异步运行。这是因为闭包是 @escaping
并且是从 refreshTokens
例程内的 responseJSON
中调用的。因此,should
方法将在实际调用 refreshTokens
的闭包时执行其延迟的 unlock
。
话虽如此,这并不是我见过的最优雅的代码,其中锁的用途不明确,死锁的风险如此依赖于其他例程的实现细节。貌似这里还可以,但不怪你挑眉。
我正在审查一些 Alamofire sample Retrier 代码:
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()
,然后在传递给 refreshTokens
的闭包中也使用相同的行 strongSelf.lock.lock()
。
如果执行defer
解锁时第一个锁直到should
方法结束才释放,那么第二个strongSelf.lock.lock()
如何在第一个锁成功执行的同时执行举办了吗?
refreshTokens
的尾随闭包,其中调用了对 lock()
/unlock()
的第二次调用,异步运行。这是因为闭包是 @escaping
并且是从 refreshTokens
例程内的 responseJSON
中调用的。因此,should
方法将在实际调用 refreshTokens
的闭包时执行其延迟的 unlock
。
话虽如此,这并不是我见过的最优雅的代码,其中锁的用途不明确,死锁的风险如此依赖于其他例程的实现细节。貌似这里还可以,但不怪你挑眉。