Maison  >  Article  >  Java  >  Explication détaillée du mot-clé Synchronized dans la programmation multithread Java

Explication détaillée du mot-clé Synchronized dans la programmation multithread Java

高洛峰
高洛峰original
2017-01-05 14:43:381476parcourir

Cet article présente quelques points de connaissances sur le mot-clé synchronisé dans le multi-threading JAVA en tant que verrou d'objet.

Le soi-disant verrouillage d'objet est le verrouillage synchronisé d'un objet. Concernant les verrouillages d'objets, veuillez vous référer à : cet article

1. L'analyse

synchronisée peut modifier les méthodes d'instance, comme suit :

public class MyObject {
  synchronized public void methodA() {
    //do something....
  }

Ici, le mot-clé synchronisé verrouille l'objet courant. C’est aussi pourquoi on l’appelle verrouillage d’objet.

Pourquoi l'objet actuel est-il verrouillé ? Parce que methodA() est une méthode d'instance, si vous souhaitez exécuter methodA(), vous devez l'appeler sous la forme de object.method() (obj.methodA(). obj est un objet de la classe MyObject. Verrous synchronisés l'objet obj.

Le code ci-dessus peut également s'écrire comme ceci :

public class MyObject {
 
  public void methodA() {
    synchronized(this){
      //do something....
    }
  }

La caractéristique est la suivante : lorsque plusieurs méthodes d'instance synchronisées sont définies dans la classe MyObject, si plusieurs threads possèdent le même objet du MyObject, ces méthodes ne peuvent être exécutées que de manière synchrone. Autrement dit, après avoir exécuté une méthode modifiée synchronisée, une autre méthode modifiée synchronisée peut être exécutée.

est la suivante :

Il existe deux méthodes modifiées synchronisées dans la classe MyObject.
public class MyObject {
 
  synchronized public void methodA() {
    //do something....
  }
 
  synchronized public void methodB() {
    //do some other thing
  }
}

Le thread A exécute la méthodeA()
public class ThreadA extends Thread {
 
  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodA();
  }
}

Thread B Exécuter methodB()
public class ThreadB extends Thread {
 
  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodB();
  }
}

Puisque le thread A et le thread B détiennent le même objet de classe MyObject, bien que les deux threads doivent appeler une méthode différente, mais cela doit être synchrone. Par exemple, le thread B doit attendre que le thread A ait fini d'exécuter la méthode methodA() avant de pouvoir exécuter la méthode methodB().
public class Run {
  public static void main(String[] args) {
    MyObject object = new MyObject();
 
    //线程A与线程B 持有的是同一个对象:object
    ThreadA a = new ThreadA(object);
    ThreadB b = new ThreadB(object);
    a.start();
    b.start();
  }
}

3. Conclusion

Comme le montre ce qui précède, la portée du verrou synchronisé décrit dans cet article est l'objet entier. S'il existe plusieurs méthodes de synchronisation modifiées synchronisées dans une classe et que plusieurs threads contiennent le même objet de la classe (le même objet de la classe), même s'ils appellent des méthodes différentes, l'exécution de chaque méthode est également synchronisée.

S'il n'y a pas de variables partagées entre les méthodes synchronisées, ou s'il n'y a pas de connexion entre les méthodes, mais qu'elles ne peuvent être exécutées que de manière synchrone, cela affectera l'efficacité.

4. Application - Utiliser synchronisé pour éviter de lire des données sales en raison d'une incohérence des données

L'exemple suivant :

methodA() est responsable de la modification du nom d'utilisateur et du mot de passe. En réalité, un nom d'utilisateur correspond à un mot de passe.
public class MyObject {
 
  private String userName = "b";
  private String passWord = "bb";
   
  synchronized public void methodA(String userName, String passWord) {
    this.userName = userName;
    try{
      Thread.sleep(5000);
    }catch(InterruptedException e){
       
    }
    this.passWord = passWord;
  }
 
  synchronized public void methodB() {
    System.out.println("userName" + userName + ": " + "passWord" + passWord);
  }
}

methodB() se charge de lire le nom d'utilisateur et le mot de passe.

Si methodB() n'est pas modifié avec synchronisé, le thread A appelle methodA() et s'exécute à la ligne 7, change le nom d'utilisateur et abandonne le processeur pour une raison quelconque (comme dormir sur la ligne 9).

À ce stade, si le thread B exécute la méthodeB(), le nom d'utilisateur lu est le nom d'utilisateur modifié par le thread A ("a"), mais le mot de passe est le mot de passe d'origine ("bb" ). Parce que le thread A s'est endormi et n'a pas eu le temps de changer le mot de passe.

Cependant, si la méthodeB() est modifiée avec synchronisé, alors le thread B ne peut qu'attendre que le thread A termine son exécution (c'est-à-dire changer le nom d'utilisateur et le mot de passe) avant d'exécuter la méthode B pour lire le nom d'utilisateur et mot de passe. Par conséquent, les problèmes de lecture sale causés par l’incohérence des données sont évités.

Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à tout le monde dans l'apprentissage de la programmation Java.

Pour des explications plus détaillées sur le mot-clé Synchronized dans la programmation multithread Java et les articles associés, veuillez faire attention au site Web PHP chinois !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn