2017-08-16 4 views
2

J'écris une application web, donc la concurrence est concernée. Je dois appeler une API avec un jeton expiré toutes les 10 minutes, donc avant chaque appel d'API, je dois vérifier les nouveaux jetons.Est-ce que le verrouillage entre deux mêmes instructions conditionnelles est bon?

Je n'ai aucune expérience avec la conception simultanée, donc c'est ce que je fais et j'ai besoin de quelqu'un pour clarifier si je me porte bien. Est-ce anti-pattern? Note: la classe elle-même est singleton.

private object tokenLock = new object(); 
    private void RequestApi() 
    { 
     if (DateTime.UtcNow >= this.TokenExpireTime) 
     { 
      lock (this.tokenLock) 
      { 
       if (DateTime.UtcNow >= this.TokenExpireTime) 
       { 
        // Request new Token 
        // Update new Token Expiration Time 
       } 
      } 
     } 

     // Request API 
    } 

Pour empêcher le code dupliquée, je peux réécrire dans une propriété (la logique est toujours la même):

private void RequestApi() 
    { 
     if (this.NeedNewToken) 
     { 
      lock (this.tokenLock) 
      { 
       if (this.NeedNewToken) 
       { 
        // Request new Token 
        // Update new Token Expiration Time 
       } 
      } 
     } 

     // Request API 
    } 

    private bool NeedNewToken => DateTime.UtcNow >= this.TokenExpireTime; 
+2

Cela appartient plus à CodeReview qu'à StackOverflow – derape

+0

En fait, je pense que je devrais même faire une fonction, appelons-la "EnsureToken()", qui encapsule ce modèle. Si le modèle lui-même est une mauvaise pratique est un autre problème, cependant. Je crains que cela ne soit fermé car "principalement orienté". – Fildor

+0

Vous avez correctement validé deux fois avec un verrou intermédiaire. L'utilisation d'une propriété ou non est basée sur l'opinion. Mais assurez-vous également de verrouiller le processus d'écriture à 'TokenExpireTime'. Sinon, vous pourriez finir par lire 'TokenExpireTime' en écrivant dessus. Le résultat serait inconnu dans ce cas. –

Répondre

2

Vous devez vous débarrasser de la comparaison externe, désynchronisé. Tout d'abord, le modèle que vous utilisez s'appelle "double-checked locking". Il est généralement utilisé uniquement dans les situations où il y a un haut niveau de contention et une faible probabilité de devoir prendre le verrou, justifiant la maladresse du code.

Sur cette seule base, il est peu probable que vous ayez vraiment besoin de l'utiliser dans ce cas. Cependant, j'admets qu'à cet égard, la question est une question d'opinion. Mais le plus important, c'est que le double contrôle de verrouillage dépend de la possibilité de faire le test conditionnel en toute sécurité sans synchronisation, ce qui n'est pas le cas ici. La valeur DateTime n'est pas une primitive et ne peut donc pas être accessible en toute sécurité sans synchronisation. Dans le cas contraire, vous risquez d'obtenir une valeur "déchirée", c'est-à-dire une valeur partiellement écrite et donc, ni l'ancienne valeur ni la nouvelle valeur. À cet égard, la question est pas une question d'opinion. Le code est simplement incorrect et doit être corrigé. Prends juste la serrure, et fais ce que tu as besoin de faire à l'intérieur de la serrure. N'essayez pas de raccourcir avec une comparaison non synchronisée. Ce n'est pas sûr dans ce cas.