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 !