En tant qu'outil permettant de partager simultanément des données et d'assurer la cohérence, les verrous ont plusieurs implémentations sur la plate-forme JAVA (telles que synchronisées et ReentrantLock, etc.). Ces verrous déjà écrits facilitent notre développement, mais la nature et le type spécifiques des verrous sont rarement mentionnés. Cette série d'articles analysera les noms et caractéristiques courants des verrous sous JAVA pour répondre à vos questions.
4. Verrouillage réentrant :
Cet article parle des verrous réentrants au sens large, et pas seulement de ReentrantLock sous JAVA.
Les verrous réentrants, également appelés verrous récursifs, signifient qu'une fois que la fonction externe du même thread a acquis le verrou, la fonction récursive interne a toujours le code pour acquérir le verrou, mais cela n'est pas affecté.
Dans l'environnement JAVA, ReentrantLock et synchronisé sont tous deux des verrous réentrants.
Voici des exemples d'utilisation :
Copiez le code comme suit :
classe publique Test implémente Runnable{
public synchronisé void get(){
System.out.println(Thread.currentThread().getId());
ensemble();
}
ensemble vide synchronisé public(){
System.out.println(Thread.currentThread().getId());
}
@Outrepasser
public void run() {
obtenir();
}
public static void main (String[] arguments) {
Test ss=nouveau Test();
nouveau fil(ss).start();
nouveau fil(ss).start();
nouveau fil(ss).start();
}
}
Les résultats finaux des deux exemples sont corrects, c'est-à-dire que le même ID de thread est généré deux fois de suite.
Le résultat est le suivant :
Copiez le code comme suit :
Fil de discussion : 8
Fil de discussion : 8
ID de discussion : 10
ID de discussion : 10
ID de discussion : 9
ID de discussion : 9
Le rôle principal des verrous réentrants est d’éviter les blocages.
Prenons le verrouillage de rotation comme exemple.
Copiez le code comme suit :
classe publique SpinLock {
private AtomicReference<Thread> propriétaire =new AtomicReference<>();
verrou public vide(){
Courant du fil = Thread.currentThread();
while(!owner.compareAndSet(null, current)){
}
}
déverrouillage du vide public () {
Courant du fil = Thread.currentThread();
propriétaire.compareAndSet (actuel, null);
}
}
Pour les verrous tournants :
1. Si le même thread appelle lock() deux fois, la position du verrou sera appelée une deuxième fois. Si un blocage se produit, cela signifie que le verrou n'est pas réentrant. (Dans la fonction de verrouillage, vous devez vérifier si le thread est le thread qui a obtenu le verrou)
2. Si le problème 1 a été résolu, le verrou aura été libéré lorsque unlock() sera appelé pour la première fois. Le verrou ne doit pas être déverrouillé.
(Utiliser les temps de comptage pour les statistiques)
Après modification, cela se présente comme suit :
Copiez le code comme suit :
classe publique SpinLock1 {
private AtomicReference<Thread> propriétaire =new AtomicReference<>();
nombre entier privé =0 ;
verrou public vide(){
Courant du fil = Thread.currentThread();
if(current==owner.get()) {
compte++;
retour ;
}
while(!owner.compareAndSet(null, current)){
}
}
déverrouillage du vide public () {
Courant du fil = Thread.currentThread();
if(current==owner.get()){
si(compte !=0){
compter--;
}autre{
propriétaire.compareAndSet (actuel, null);
}
}
}
}
Ce verrou tournant est un verrou réentrant.