我有一个访问关键变量的函数,需要对它进行互斥访问,但是通过完成处理程序返回。
这是我目前正在尝试使用的方法:
static func getAccessTokenValue(completionHandlerResult : @escaping (_ accesstoken:String) -> ()) {
tokenQ.sync {
let expire_in_str = UserDefaults.standard.value(forKey: "expires_in") as! String
print(expire_in_str)
let accessToken_time = UserDefaults.standard.value(forKey: "access_token_time") as! Date
let todayDate = Date()
let seconds = (Calendar.current as NSCalendar).components(.second, from: accessToken_time, to: todayDate, options: []).second
if seconds! < Int(5) {
print("success")
completionHandlerResult( Constants.Access_Token)
}
else {
refreshLock.wait()
self.renewAccessToken(completionHandler: { accesstokenValue in
tokenQ.sync {
completionHandlerResult(accesstokenValue)
}
})
refreshLock.signal()
}
}
}
目标是一次只能有一个线程使用self.renewAccessToken
。单独使用DispatchQueue.sync
并没有实现这一点,所以我转移到信号量,但上面的代码导致死锁,因为看起来refreshLock.signal()
没有效果。
self.renewAccessToken
使用alamofire,并在其中包含另一个完成处理程序,这会增加线程问题。
我遇到的主要问题是多个线程正在尝试同时续订相同的令牌,一旦一个线程更新令牌,其他线程会保留旧令牌并且其续订请求被拒绝,因为令牌只能是续约一次。
处理这种情况的最佳方法是什么?
答案 0 :(得分:0)
试试这个:
static func getAccessTokenValue(completionHandlerResult : @escaping (_ accesstoken:String) -> ()) {
tokenQ.sync {
let expire_in_str = UserDefaults.standard.value(forKey: "expires_in") as! String
let accessToken_time = UserDefaults.standard.value(forKey: "access_token_time") as! Date
let todayDate = Date()
let seconds = (Calendar.current as NSCalendar).components(.second, from: accessToken_time, to: todayDate, options: []).second
if seconds! < Int(5) {
completionHandlerResult( Constants.Access_Token)
}
else {
refreshLock.wait()
self.renewAccessToken(completionHandler: { accesstokenValue in
completionHandlerResult(accesstokenValue)
})
refreshLock.signal()
}
}
}