2

중요한 변수에 액세스하고 상호 배타적 인 액세스가 필요하지만 완료 핸들러를 통해 반환하는 함수가 있습니다.스위프트 : 완료 처리기로 멀티 스레딩

이 내가 현재이 시도 사용하고 무엇을 :

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

이 시도 :

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() 
     } 
    } 
}