2016-10-15 3 views
3

私はいくつかのAlamofire sample Retrierコード見直している:私はあなたが関数の最初の行にlock.lock()を持っているし、その後もrefreshTokensに渡されたクロージャ内の同じラインstrongSelf.lock.lock()を持つことができる方法に従わないNSLock.lock()はすでにロックされている間に実行されましたか?

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

を。

deferロック解除は、次に実行されるときに最初のロックがshould方法が終了するまで解放されない場合、最初のロックが保持されている間どのように第二strongSelf.lock.lock()を正常に実行しますか?

答えて

4

lock()/への2番目の呼び出しが呼び出されるrefreshTokensの末尾のクロージャが非同期に実行されます。これは、クロージャーが@escapingであり、ルーチン内のresponseJSON内から呼び出されているためです。そのため、shouldメソッドは、refreshTokensのクロージャが実際に呼び出される時点までに遅延が実行されます(unlock)。

これは、ロックの有用性が不明で、デッドロックのリスクが他のルーチンの実装の詳細に大きく依存する、私が見てきた最もエレガントなコードではありません。ここではOKのようですが、私はあなたにそれを眉を上げることを責めません。

関連する問題