Java并发——Synchronized及其实现原理

2017-07-25  本文已影响583人  李牙刷儿

Synchronized是Java中实现进程同步最简单的一种方式,Synchronized主要有以下三个作用:

接下来我们就来看下Synchronized的实现原理,看看Synchronized是如何实现上述三个作用的。

Synchronized有三种常用方法:

具体的用法这里就不展开了,不熟悉的朋友建议先试用一下。

1 Synchronized实现原理

先来看下下面这段代码:

public class SynchronizedDemo {
     public void method() {
         synchronized (this) {
             System.out.println("Method 1 start");
         }
     }
 }

这是一个典型的Synchronized修饰代码块的例子,Synchronized的对象是实例对象。意味着对一个SynchronizedDemo对象,同一时间内只能有一个线程可以执行method方法。

接下来我们来看看上述代码对应的字节码:

这里写图片描述

可以看到synchronized所覆盖的代码块的首尾部分分别加上了monitorentermonitorexit。JVM中对于上述两条指令的解释如下:

通过上述两段描述便不难理解Synchronized的实现原理了。Synchronized实际是通过关联一个对象的monitor来实现的。在前文的代码demo中,关联的对象实际就是SynchonizedDemo实例对象的monitor。其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。

接下来再来看看Synchronized修饰方法的场景:

public class SynchronizedMethod {
     public synchronized void method() {
         System.out.println("Hello World!");
     }
 }

对应的字节码为:

这里写图片描述

从反编译的结果来看,方法的同步并没有通过指令monitorenter和monitorexit来完成(理论上其实也可以通过这两条指令来实现),不过相对于普通方法,其常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的:当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。 其实本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。

当Synchronized修饰不同方法时,获取的monitor对象不同:

通过上述解释,相信大家已经知道Synchronized是如何保证互斥性的,那么其是怎么实现可见性和顺序性的呢?其实也跟monitor相关:

上一篇 下一篇

猜你喜欢

热点阅读