Maison  >  Article  >  Java  >  Verrouillage de classe Java, verrouillage d'objet, test de conflit de verrouillage privé

Verrouillage de classe Java, verrouillage d'objet, test de conflit de verrouillage privé

高洛峰
高洛峰original
2017-01-19 13:41:401302parcourir

Les verrous de classe et les verrous d'objets seront-ils en conflit ? Les verrous d'objet et les verrous privés entreront-ils en conflit ? Illustration à travers des exemples.

1. Accords pertinents

Afin de clarifier la description suivante, nous concluons d'abord l'accord suivant sur les définitions pertinentes des serrures impliquées dans cet article :

1. lock : dans le code Ajoutez des verrous statiques et synchronisés aux méthodes dans le code, ou des segments de code synchronisés (xxx.class), tels que increament() ci-dessous

2. dans le verrou de code, ou le segment de code synchronisé (ce), tel que synOnMethod() et synInMethod() ci-dessous

3. Private lock : Déclarez une propriété privée telle que le verrou d'objet privé à l'intérieur de la classe et verrouillez. si nécessaire Le segment de code synchronisé (verrouillage), tel que synMethodWithObj() ci-dessous.

2. Code de test

1. Écrivez une classe de démarrage ObjectLock

public class ObjectLock {
 public static void main(String[] args) {
  System.out.println("start time = " + System.currentTimeMillis()+"ms");
  LockTestClass test = new LockTestClass();
  for (int i = 0; i < 3; i++) {
   Thread thread = new ObjThread(test, i);
   thread.start();
  }
 }
}

2. Écrivez une classe de thread ObjThread pour démarrer la méthode de synchronisation (notez son exécution La méthode. peut être ajusté pour différents tests)

public class ObjThread extends Thread {
 LockTestClass lock;
 int i = 0;
 public ObjThread(LockTestClass lock, int i) {
  this.lock = lock;
  this.i = i;
 }
 public void run() {
  //无锁方法
//  lock.noSynMethod(this.getId(),this);
  //对象锁方法1,采用synchronized synInMethod的方式
  lock.synInMethod();
  //对象锁方法2,采用synchronized(this)的方式
//  lock.synOnMethod();
  //私有锁方法,采用synchronized(object)的方式
//  lock.synMethodWithObj();
  //类锁方法,采用static synchronized increment的方式
  LockTestClass.increment();
 }
}

3. Écrivez une classe de test de verrouillage LockTestClass, comprenant diverses méthodes de verrouillage

public class LockTestClass {
 //用于类锁计数
 private static int i = 0;
    //私有锁
 private Object object = new Object();
 /**
  * <p>
  * 无锁方法
  *
  * @param threadID
  * @param thread
  */
 public void noSynMethod(long threadID, ObjThread thread) {
  System.out.println("nosyn: class obj is " + thread + ", threadId is"
    + threadID);
 }
 /**
  * 对象锁方法1
  */
 public synchronized void synOnMethod() {
  System.out.println("synOnMethod begins" + ", time = "
    + System.currentTimeMillis() + "ms");
  try {
   Thread.sleep(2000L);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("synOnMethod ends");
 }
 /**
  * 对象锁方法2,采用synchronized (this)来加锁
  */
 public void synInMethod() {
  synchronized (this) {
   System.out.println("synInMethod begins" + ", time = "
     + System.currentTimeMillis() + "ms");
   try {
    Thread.sleep(2000L);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("synInMethod ends");
  }
 }
 /**
  * 对象锁方法3
  */
 public void synMethodWithObj() {
  synchronized (object) {
   System.out.println("synMethodWithObj begins" + ", time = "
     + System.currentTimeMillis() + "ms");
   try {
    Thread.sleep(2000L);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("synMethodWithObj ends");
  }
 }
 /**
  * 类锁
  */
 public static synchronized void increament() {
  System.out.println("class synchronized. i = " + i + ", time = "
    + System.currentTimeMillis() + "ms");
  i++;
  try {
   Thread.sleep(2000L);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
   System.out.println("class synchronized ends.");
 }
}

3. Testez le verrouillage de classe et le verrouillage d'objet. La méthode d'exécution d'ObjectThread est modifiée comme suit :

Sortie du terminal :
public void run() {
  //无锁方法
//  lock.noSynMethod(this.getId(),this);
  //对象锁方法1,采用synchronized synInMethod的方式
  lock.synInMethod();
  //对象锁方法2,采用synchronized(this)的方式
//  lock.synOnMethod();
  //私有锁方法,采用synchronized(object)的方式
//  lock.synMethodWithObj();
  //类锁方法,采用static synchronized increment的方式
  LockTestClass.increament();
 }

Vous pouvez voir que la méthode de verrouillage d'objet (synInMothod ) est 2. secondes plus rapide que la méthode de verrouillage de classe (increament) lors de son premier démarrage. En effet, lorsque synInMehtod est exécuté, il dort pendant 2 secondes puis exécute increament, et ces deux méthodes partagent le même thread, ce sera donc 2 secondes plus lent. . Si increament Placez-le devant synInMethod lors de l'exécution, alors il sera increament 2 secondes plus rapide lorsqu'il sera démarré pour la première fois.
start time = 1413101360231ms
synInMethod begins, time = 1413101360233ms
synInMethod ends
class synchronized. i = 0, time = 1413101362233ms
synInMethod begins, time = 1413101362233ms
class synchronized ends.
synInMethod ends
class synchronized. i = 1, time = 1413101364233ms
synInMethod begins, time = 1413101364233ms
class synchronized ends.
synInMethod ends
class synchronized. i = 2, time = 1413101366234ms
class synchronized ends.

Lorsque la méthode de verrouillage de classe est démarrée, la méthode de verrouillage d'objet d'un autre thread est également démarrée presque en même temps, indiquant que les deux n'utilisent pas le même verrou et qu'il n'y aura pas de concurrence.

Conclusion : les verrous de classe et les verrous d'objet ne seront pas en concurrence, et leurs méthodes de verrouillage ne s'affecteront pas.

2. Verrouillage privé et verrouillage d'objet, la méthode d'exécution d'ObjectThread est modifiée comme suit :

Sortie du terminal :
public void run() {
  //无锁方法
//  lock.noSynMethod(this.getId(),this);
  //对象锁方法1,采用synchronized synInMethod的方式
  lock.synInMethod();
  //对象锁方法2,采用synchronized(this)的方式
//  lock.synOnMethod();
  //私有锁方法,采用synchronized(object)的方式
  lock.synMethodWithObj();
  //类锁方法,采用static synchronized increment的方式
//  LockTestClass.increament();
 }

Elle est très similaire à verrouillage de classe et verrouillage d'objet.
start time = 1413121912406ms
synInMethod begins, time = 1413121912407ms.
synInMethod ends.
synMethodWithObj begins, time = 1413121914407ms
synInMethod begins, time = 1413121914407ms.
synInMethod ends.
synMethodWithObj ends
synInMethod begins, time = 1413121916407ms.
synMethodWithObj begins, time = 1413121916407ms
synInMethod ends.
synMethodWithObj ends
synMethodWithObj begins, time = 1413121918407ms
synMethodWithObj ends

Conclusion : les verrous privés et les verrous d'objet ne seront pas en concurrence, et leurs méthodes de verrouillage ne s'affecteront pas.

3.synchronized est directement ajouté à la méthode et synchronisé(this). La méthode d'exécution d'ObjectThread est modifiée comme suit :

Sortie du terminal :
public void run() {
  //无锁方法
//  lock.noSynMethod(this.getId(),this);
  //对象锁方法1,采用synchronized synInMethod的方式
  lock.synInMethod();
  //对象锁方法2,采用synchronized(this)的方式
  lock.synOnMethod();
  //私有锁方法,采用synchronized(object)的方式
//  lock.synMethodWithObj();
  //类锁方法,采用static synchronized increment的方式
//  LockTestClass.increament();
 }

Vous pouvez veiller à ce que les deux sorties soient strictement en série (bien sûr, il n'est pas déterminé si synInMethod ou synOnMethod est exécuté en premier lors de la nouvelle exécution, selon qui obtient le verrou).
start time = 1413102913278ms
synInMethod begins, time = 1413102913279ms
synInMethod ends
synInMethod begins, time = 1413102915279ms
synInMethod ends
synOnMethod begins, time = 1413102917279ms
synOnMethod ends
synInMethod begins, time = 1413102919279ms
synInMethod ends
synOnMethod begins, time = 1413102921279ms
synOnMethod ends
synOnMethod begins, time = 1413102923279ms
synOnMethod ends

Conclusion : synchronisé directement ajouté à la méthode et synchronisé(ce) verrouillent tous deux l'objet courant. Les deux méthodes de verrouillage sont dans une relation compétitive, et une seule méthode peut être exécutée en même temps.

Pour plus d'articles sur les verrous de classe Java, les verrous d'objet et les tests de conflits de verrous privés, veuillez prêter 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