若有收获,请记得分享和转发哦
前言
synchronized,是解决并发情况下数据同步访问问题的一把利刃。那么synchronized的底层原理是什么呢?下面我们来一层一层剥开它的心,就像剥洋葱一样,看个究竟。
Synchronized的使用场景
synchronized关键字可以作用于方法或者代码块,最主要有以下几种使用方式,如图:
接下来,我们先剥开synchronized的第一层,反编译其作用的代码块以及方法。
synchronized作用于代码块
public class SynchronizedTest {
public void doSth(){
synchronized (SynchronizedTest.class){
System.out.println("test Synchronized" );
}
}
}
反编译,可得:
由图可得,添加了synchronized关键字的方法,多了ACCSYNCHRONIZED标记。即JVM通过在方法访问标识符(flags)中加入ACCSYNCHRONIZED来实现同步功能。
monitorenter、monitorexit、ACC_SYNCHRONIZED
剥完第一层,反编译synchronized的方法以及代码块,我们已经知道synchronized是通过monitorenter、monitorexit、ACC_SYNCHRONIZED实现同步的,它们三作用都是啥呢?我们接着剥第二层:
monitorenter
monitorenter指令介绍
monitorexit
monitorexit指令介绍
ACC_SYNCHRONIZED
ACC_SYNCHRONIZED介绍
Synchronized第二层的总结
同步代码块是通过monitorenter和monitorexit来实现,当线程执行到monitorenter的时候要先获得monitor锁,才能执行后面的方法。当线程执行到monitorexit的时候则要释放锁。
同步方法是通过中设置ACCSYNCHRONIZED标志来实现,当线程执行有ACCSYNCHRONI标志的方法,需要获得monitor锁。
每个对象维护一个加锁计数器,为0表示可以被其他线程获得锁,不为0时,只有当前锁的线程才能再次获得锁。
同步方法和同步代码块底层都是通过monitor来实现同步的。
每个对象都与一个monitor相关联,线程可以占有或者释放monitor。
好的,剥到这里,我们还有一些不清楚的地方,monitor是什么呢,为什么它可以实现同步呢?对象又是怎样跟monitor关联的呢?客观别急,我们继续剥下一层,请往下看。
看完上图,其实对象跟monitor怎样关联,我们已经有个大概认识了,接下来我们分对象内存布局,对象头,MarkWord一层层继续往下探讨。
对象的内存布局
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对象填充(Padding)。
总结
我们直接以一张Synchronized洋葱图作为总结吧,如果你愿意一层一层剥开我的心。
点个在看 就是最好的支持