La gestion de l'accès aux ressources partagées est importante en programmation simultanée pour garantir la cohérence des données. Le mot clé synchronisé traditionnel manque de flexibilité pour des scénarios complexes comme l'équité, l'acquisition immédiate d'un verrou, l'attente d'un moment précis pour acquérir le verrou, etc. Les API Lock, ReadWriteLock et StampedLock sont introduites dans Java 1.5 pour résoudre ces limitations et offrir un grand contrôle aux développeurs pour gérer accès aux ressources partagées. Ils font partie du package java.util.concurrent.
API de verrouillage
Lock API est une interface et fournit les méthodes ci-dessous pour gérer la synchronisation des threads.
- void lock() Il est utilisé pour acquérir le verrou. Si le verrou n'est pas disponible, le fil sera bloqué jusqu'à ce que le verrou soit acquis.
-
void lockInterruptably() C'est la même chose que lock(), mais ce fil peut être interrompu.
-
boolean tryLock() Renvoie vrai si le verrou est acquis ; sinon, faux. Le fil ne sera pas bloqué si le verrou n'est pas accordé.
-
boolean tryLock (long timeout, unité TimeUnit) C'est la même chose que tryLock() mais attend uniquement une durée spécifiée.
-
void unlock() Libère le verrou.
-
Condition newCondition() Permet à un thread d'attendre qu'une condition se produise lors de l'exécution de la partie critique.
ReentrantLock
- La classe ReentrantLock implémente l'interface Lock.
- Un verrou réentrant permet à un thread d'acquérir un verrou plusieurs fois et de le libérer plusieurs fois.
- Si vous souhaitez une politique d'équité, utilisez le constructeur paramétré de ReentrantLock.
- Si l'équité est activée, il garantit que le thread en attente le plus long a accès au verrou.
- Utilisez enfin le bloc pour libérer le verrou afin d'éviter une situation de blocage.
ReentrantLock lock = new ReentrantLock(true); //fair lock
public void methodExecution() {
lock.lock();
try {
// Critical section here
} finally {
lock.unlock();
}
}
Copier après la connexion
Copier après la connexion
API ReadWriteLock
L'API ReadWriteLock est une interface et maintient une paire de verrous pour maintenir les scénarios de lecture et d'écriture. Le verrou de lecture peut être détenu simultanément par plusieurs threads s'il n'y a pas d'écrivains. Le verrou en écriture est exclusif.
-
Lock readLock() - Renvoie le verrou utilisé pour la lecture.
-
Lock writeLock() - Renvoie le verrou utilisé pour l'écriture.
Règles clés
- Si vous disposez d'un verrou en lecture, vous ne pouvez pas acquérir de verrou en écriture.
- Si vous disposez d'un verrou en écriture, vous ne pouvez acquérir un verrou en lecture dans aucun autre fil de discussion.
- Si vous disposez d'un verrou en écriture, vous pouvez en acquérir un autre dans le même fil de discussion.
- Un verrou en écriture est autorisé lorsqu'aucun autre verrou en lecture ou en écriture n'est actif.
- En attendant un verrou en écriture, aucun nouveau verrou en lecture provenant d'autres threads n'est autorisé.
RéentrantReadWriteLock
- La classe ReentrantReadWriteLock implémente l'interface ReadWriteLock.
- Utile si nous avons plus de lecture que d'écriture.
Exemple : dans la communication par micro-service, supposons que le service B attend un JWT du service A. JWT est généré par le service A et peut être mis en cache pendant quelques minutes. Dans ces scénarios, ReentrantReadWriteLock sera plus utile. Nous pouvons renouveler le token s'il est expiré ou sur le point d'expirer. Je n'acquiers pas de verrou de lecture ici pour éviter la famine en lecture.
ReentrantLock lock = new ReentrantLock(true); //fair lock
public void methodExecution() {
lock.lock();
try {
// Critical section here
} finally {
lock.unlock();
}
}
Copier après la connexion
Copier après la connexion
API StampedLock
StampedLock a été introduit dans Java 8 et c'est une classe. Il prend en charge trois modes de verrouillage et renvoie un tampon utilisé pour déverrouiller le verrou. Il permet la mise à niveau du verrouillage.
-
Read Lock Permet à plusieurs threads de lire simultanément.
-
Write Lock Renvoie un verrou utilisé pour l'écriture.
-
Verrouillage de lecture optimiste Permet à un thread de lire sans acquérir un verrou de lecture traditionnel, ce qui améliore les performances en évitant les conflits.
-
long writeLock() Acquiert le verrou exclusif, le bloquant si nécessaire jusqu'à ce qu'il soit disponible.
-
void unlockWrite(long stamp) Libère le verrou en écriture.
-
long readLock() Acquiert le verrou de lecture, bloque si un verrou d'écriture est en cours.
-
void unlockRead(long stamp) Libère le verrou de lecture.
-
long tryOptimisticRead() Renvoie un tampon qui peut être validé ultérieurement, ou zéro s'il est exclusivement verrouillé.
-
boolean validate(long stamp) Renvoie vrai si le verrou n'a pas été acquis exclusivement (verrouillage en écriture) depuis l'émission du tampon donné ; sinon, faux.
-
long tryConvertToWriteLock(long stamp) Met à niveau un verrou de lecture ou optimiste vers un verrou d'écriture. Bloque jusqu'à ce qu'il soit disponible.
Points clés :
- Il n'est pas réentrant, ce qui signifie qu'un thread détenant un verrou ne peut pas l'acquérir à nouveau.
- Il ne prend pas en charge les conditions.
- Cela ne soutient pas l’équité.
String jwt = JwtUtil.generateJwt();
ReadWriteLock lock = new ReentrantReadWriteLock();
Lock writeLock = lock.writeLock();
Lock readLock = lock.readLock();
public String getJwt(String key, String value) {
if (StringUtils.hasLength(jwt)) {
if (JwtUtil.isJwtEligibleToRenew(jwt)) {
generateJwt();
}
} else {
generateJwt();
}
return this.jwt;
}
public void generateJwt() {
this.writeLock.lock(); //write lock
try {
if (JwtUtil.isJwtEligibleToRenew(jwt)) {
this.jwt = JwtUtil.generateJwt();
}
} finally {
this.writeLock.unlock(); //release write lock
}
}
Copier après la connexion
Exemple de lecture optimiste. Cela permet à un thread de lire sans acquérir un verrou de lecture traditionnel, ce qui améliore les performances en évitant les conflits de verrouillage. Si un verrou en écriture est acquis après avoir acquis un temps de verrouillage en lecture optimiste, validate() renverra false sinon ce sera vrai.
public void readAndWrite() {
long l = this.stampedLock.readLock();
try {
//critical section
} finally {
this.stampedLock.unlock(l);
}
long w = this.stampedLock.writeLock();
try {
//critical section
} finally {
this.stampedLock.unlock(w);
}
}
Copier après la connexion
Bon codage et apprentissage !!!
Veuillez laisser un commentaire si vous avez des questions.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!