synchronzied 原理

synchronzied

使用

1. 代码块:锁括号对象
2. 普通方法:锁当前调用对象
3. 静态方法:锁当前class对象

源码解析

1. 代码块上通过javap反编译出来可看到monitorenter和monitorexit对称使用来完成同步。
monitorenter主要判断锁对象对应的monitor计数是否=0,如果是则这个对象对应的monitor计数+1,获取锁成功,否则阻塞。
monitorexit则是对锁对象对应的monitor对象计数-1直到0为成功释放。

2. 普通方法与静态方法通过javap反编译出来则是在方法表中的flags里的ACC_SYNCHRONIZED来表示是否是同步方法
当线程调用方法时,判断这个方法设置了ACC_SYNCHRONIZED时,则对锁对象对应的monitor计数+1,结束事进行-1释放。否则阻塞

JVM对synchronzied 的优化

1. 偏向锁
2. 轻量级锁
3. 自旋锁
4. 自适应自旋锁
5. 锁消除
6. 锁粗化

1.偏向锁:获取锁对象的mark word,则进行CAS操作,并把线程id指向自己,成功则获取成功,执行完同步方法后,它不会进行释放,它会等到竞
争对象进来获取的时候触发,并释放。当偏向锁膨胀后会升级为轻量级锁
2.轻量级锁:获取锁对象的mark word,并copy一份到线程栈桢中,然后对锁对象的mark word进行CAS操作替换状态信息,并把线程指针指向当前
线程,如果失败则进行自旋CAS,一直失败,则膨胀为重量级锁并对mark word的状态信息修改后阻塞。释放时:对mark word进行CAS替换,如果
失败则表示期间有竞争对象存在,释放锁并唤醒其它线程。
3.自旋锁:一直循环获取,循环到一定次数后进行阻塞
4.自适应自旋锁:根据前一次自旋是否成功,如果成功则判断自旋成功机率高对自旋次数进行变多,如果失败则对自旋次数进行变少甚至不进行自
旋。
5.锁消除:JVM根据数据分析进行锁消除,比如:分析一个方法里面变量并不会出现安全问题的话,则进行锁消除。
6.锁粗化:一般同步代码都是以同步少的代码块,因为当发生竞争时,可更快的由其它线程获得锁。但是如果出现连续锁代码,释放锁,这样会导致
不必要的资源消耗,所以对连续锁扩展为一个大锁会比较好点。

你可能感兴趣的:(java)