一说到并发,大家都会想起synchronized关键字,因为它帮我们解决了大多数场景下的并发问题,那么它是怎样实现的?原理又是什么?
本文将解析伟大的synchronized的作用以及原理:
synchronized主要有3个作用:
1、 确保多线程互斥的访问同步代码
2、 保证共享变量的修改能够及时可见
3、 有效解决重排序问题
关于什么是互斥什么是及时可见这些语义具体可以百度一下,本文将不再做介绍。
我们先看一段代码:
上一段代码对synchronized写了两中方式的用法,我们根据javap反编译后的syncTest.class文件:
我们看到有个monitorenter和monitorexit。从字面上来说就是监视器进入,监视器退出。那么这又代表什么呢?
在JVM语义中,每一个对象都拥有一个monitor(监视器锁),当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
执行monitorexit的线程必须是objectref所对应的monitor的所有者。
指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。
通过这两段描述,我们应该能很清楚的看出Synchronized的实现原理,Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常原因