java并发之synchronized解密

Posted Dreamer who

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java并发之synchronized解密相关的知识,希望对你有一定的参考价值。

目录

synchronized关键字主要用在4个地方:

1.实例方法

2.静态方法

3.实例方法中的代码块

4.静态方法中的代码块

监视器锁(monitor lock)所属的对象是不同的

JVM内部如何实现的

(1)实例方法中的代码块和静态方法中的代码块通过指令monitorenter和monitorexit实现的

 

(2)实例方法和静态方法JVM特殊处理,并没有相应的JVM指令对应

监视器锁(monitor lock)是可重入的,通过计数器实现

synchronized中使用的监视器锁是自动获取也是自动释放的,异常情况下也是自动释放

 


synchronized关键字在java并发编程中可以避免竞争条件,使得线程安全的访问共享数据。

synchronized关键字主要用在4个地方:

1.实例方法

2.静态方法

3.实例方法中的代码块

4.静态方法中的代码块

但是,不同的使用方式其jvm内部使用的监视器锁(monitor lock)所属的对象是不同的。

package com.doctor.thread;

/**
 * @author sdcuike
 * @date 2019-07-21
 */
public final class SynchronizedKeyWord 
    public static void main(String[] args) 
        SynchronizedKeyWord synchronizedKeyWord = new SynchronizedKeyWord();
        synchronizedKeyWord.method();
        synchronizedKeyWord.method2();

        SynchronizedKeyWord.method3();
        SynchronizedKeyWord.method5();
    

    public synchronized void method() 
        System.out.println("method:" + Thread.holdsLock(this));
    

    public void method2() 
        synchronized (this) 
            System.out.println("method2:" + Thread.holdsLock(this));
        
    


    public static synchronized void method3() 
        System.out.println("method3:" + Thread.holdsLock(SynchronizedKeyWord.class));
    

    public static void method5() 
        synchronized (SynchronizedKeyWord.class) 
            System.out.println("method5:" + Thread.holdsLock(SynchronizedKeyWord.class));
        
    


 

method:true
method2:true
method3:true
method5:true

监视器锁(monitor lock)所属的对象是不同的

上述代码所执行结果表示:synchronized用在实例方法,所使用的监视器锁(monitor lock)所属的对象为this,即当前实例对象,method2证实了这一点,即使是同一个类,不同实例也不相同。synchronized用在静态方法,所使用的监视器锁(monitor lock)所属的对象为当前类的class对象,method5证实了这一点。

JVM内部如何实现的

(1)实例方法中的代码块和静态方法中的代码块通过指令monitorenter和monitorexit实现的

 

官方文档https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.monitorenter 给出了详细的介绍。

(2)实例方法和静态方法JVM特殊处理,并没有相应的JVM指令对应

 

The monitorenter and monitorexit instructions are not used in the implementation of synchronized methods, although they can be used to provide equivalent locking semantics. Monitor entry on invocation of a synchronized method, and monitor exit on its return, are handled implicitly by the Java Virtual Machine's method invocation and return instructions, as if monitorenter and monitorexit were used.

来源:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.monitorenter

The JVM does not use any special opcodes to invoke or return from synchronized methods. When the JVM resolves the symbolic reference to a method, it determines whether the method is synchronized. If it is, the JVM acquires a lock before invoking the method. For an instance method, the JVM acquires the lock associated with the object upon which the method is being invoked. For a class method, it acquires the lock associated with the class to which the method belongs. After a synchronized method completes, whether it completes by returning or by throwing an exception, the lock is released.

来源:https://www.javaworld.com/article/2076971/how-the-java-virtual-machine-performs-thread-synchronization.html

 

 

监视器锁(monitor lock)是可重入的,通过计数器实现

 

Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:

  •  If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.
  •  If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.
  •  If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.

来源:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.monitorenter

 可重入的意思是:当前线程如果拥有了同一个监视器锁,对重入计数增1,不必重新获取。

 

synchronized中使用的监视器锁是自动获取也是自动释放的,异常情况下也是自动释放

 

One or more monitorexit instructions may be used with a monitorenter instruction (§monitorenter) to implement a synchronized statement in the Java programming language (§3.14). The monitorenter and monitorexit instructions are not used in the implementation of synchronized methods, although they can be used to provide equivalent locking semantics.

The Java Virtual Machine supports exceptions thrown within synchronized methods and synchronized statements differently:

 

  •  Monitor exit on normal synchronized method completion is handled by the Java Virtual Machine's return instructions. Monitor exit on abrupt synchronized method completion is handled implicitly by the Java Virtual Machine's athrow instruction.
  •  When an exception is thrown from within a synchronized statement, exit from the monitor entered prior to the execution of the synchronized statement is achieved using the Java Virtual Machine's exception handling mechanism (§3.14).
  • 来源:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.monitorexit

After a synchronized method completes, whether it completes by returning or by throwing an exception, the lock is released.

来源:https://www.javaworld.com/article/2076971/how-the-java-virtual-machine-performs-thread-synchronization.html

以上是关于java并发之synchronized解密的主要内容,如果未能解决你的问题,请参考以下文章

这一次,彻底搞懂Java中的synchronized关键字

JAVA多线程之先行发生原则

首发!撸了谷歌大神写的Java源码笔记后,这一次彻底搞懂Java中的synchronized关键字

Java并发编程之synchronized

深入理解Java并发之synchronized实现原理

Java并发之synchronized关键字深度解析