Analyse de l'utilisation et des scénarios d'utilisation de la programmation synchronisée

Le but de la vie est de se développer, l'essence de la vie est au changement, le défi de la vie est de conquérir
le but de la vie est de se développer, l'essence de la vie est le changement, le défi de la vie est de conquérir


Le mot clé synchronized est presque une question obligatoire pour chaque entretien. Aujourd'hui, parlons de l'utilisation de synchronized et de ses scénarios d'utilisation.

Comme nous le savons tous, il existe trois caractéristiques principales dans le modèle de mémoire Java, l' atomicité, la visibilité et l'ordre

synchronisé: garantit visibilité et atomicité

Dans le modèle de mémoire Java, synchronized stipule que lorsqu'un thread est verrouillé, il efface d'abord la mémoire de travail-> copie la dernière copie de variable de la mémoire principale dans la mémoire de travail-> exécute le code-> modifie les variables partagées La valeur est rafraîchie dans la mémoire principale-> relâchez le mutex

Ordre: l'ordre naturel dans un programme Java peut être résumé en une phrase. Si vous observez dans ce fil, toutes les opérations sont naturellement ordonnées, et si vous observez un autre fil dans un fil, toutes les opérations sont hors service. De

La synchronisation permet d'accéder à des variables ou à des blocs de code par un seul thread à la fois, ce qui réduit la consommation de mémoire. Ce qui est verrouillé est une instance d'un objet, une instance qui existe dans le tas, pas un bloc de code. Si d'autres threads souhaitent utiliser cet objet, ils doivent attendre Cet objet ne peut être obtenu que lorsqu'il est libéré, de sorte que la pensée synchronisée peut également être comprise comme un verrou pessimiste

Et regardez le mode singleton avec double verrouillage ci-dessous

     private volatile static Singleton singleton;

     public static Singleton getSingleton(){    
        if(null == singleton){        
           synchronized (Singleton.class) {            
              if(null == singleton){                
                   singleton = new Singleton();            
              }        
           }    
         }
         return singleton;
     }

     public static void main(String[] args) {    
       for(int i = 0;i<10;i++){        
          new Thread(new Runnable() {            
          @Override            
          public void run() {                
              System.out.println(Thread.currentThread().getName()+":"+Singleton.getSingleton().hashCode());            
          }}).start();    
     }复制代码


Comme vous pouvez le voir, l'objet Singleton a été modifié avec volatile, et il a été jugé à nouveau deux fois. La visibilité modifiée a été implémentée avec modification volatile (volatile est également un mot-clé). Les deux jugements sont parce que le premier jugement a été Le mode singleton n'a besoin que de créer une instance, et s'il est appelé à nouveau plus tard, il reviendra directement à l'instance précédemment créée, donc la plupart du temps, il n'est pas nécessaire d'exécuter le code dans la méthode de synchronisation, ce qui améliore considérablement les performances. Le deuxième jugement est que l'on suppose qu'après l'exécution de la première vérification par le thread 1, le thread 2 acquiert également les droits d'exécution de l'unité centrale de traitement. Ensuite, le thread 2 acquiert un verrou et crée une instance. À ce stade, le thread 1 obtient le droit d'exécution et crée également une instance. Par conséquent, plusieurs instances seront créées , vous devez donc effectuer une deuxième vérification dans le code de synchronisation. Si l'instance est vide, recréez-la de sorte qu'un seul objet soit créé.

synchronisé peut être ajouté à la méthode peut également être ajouté au bloc de code

class Sync{
     public synchronized void test() {          
         System.out.println("test开始..");          
         
         try {              
             Thread.sleep(1000);          
         } catch (InterruptedException e) {             
             e.printStackTrace();          
         }          
             System.out.println("test结束..");      
      }  
}    

class MyThread extends Thread {        

     public void run() {          
        Sync sync = new Sync();          
        sync.test();      
     }  
}   
 
public class Main {        
    
      public static void main(String[] args) {          
          for (int i = 0; i < 3; i++) {              
             Thread thread = new MyThread();              
             thread.start();          
          }      
      }  
} 
} 复制代码

Résultat de l'opération:

début du test ... début du test ... début du test ... fin du test ... fin du test ... fin du test ...

Il n'y a pas eu de changement et je n'ai pas vu la synchronisation jouer un rôle

Ensuite, nous essayons d'ajouter synchronisé au bloc de code pour réduire la granularité du verrou

class Sync {        

      public void test() {          
         synchronized (Sync.class) {              
              System.out.println("test开始..");              
         
         try {                  
              Thread.sleep(1000);              
         } catch (InterruptedException e) {                 
              e.printStackTrace();              
         }              
         System.out.println("test结束..");          
      }      
}  
}    


class MyThread extends Thread {        
      public void run() {          
          Sync sync = new Sync();          
          sync.test();      
      }  
}   


public class Main {        
     
        public static void main(String[] args) {         
        
           for (int i = 0; i < 3; i++) {              
               Thread thread = new MyThread();              
               thread.start();          
           }      
        }  
}  复制代码

运行结果: 
test开始.. test结束.. test开始.. test结束.. test开始.. test结束..复制代码

On peut voir que le verrou synchronisé n'est pas cela, mais l'objet Class Class

Réentrance synchronisée

syncronisé est un mécanisme de verrouillage interne basé sur l'atomicité et réentrant
Un thread appelle la méthode synchronisée tout en appelant une autre méthode synchronisée de l'objet dans son corps de méthode
Lorsque la sous-classe hérite de la classe parent, la sous-classe peut également appeler la méthode de synchronisation de la classe parent via le verrou réentrant

Résumé

Le verrou synchronisé est soit une instance de la classe, soit l'objet transmis, ou cette phrase, synchronisé de sorte que les variables ou les blocs de code ne sont accessibles que par un thread à la fois


Je suppose que tu aimes

Origine juejin.im/post/5e8ecce9f265da48027a2763
conseillé
Classement