Java虚拟机在操作系统层面会先尽一切可能在虚拟机层面上解决竞争关系,尽可能避免真实的竞争发生。同时,在竞争不激烈的场合,也会试图消除不必要的竞争。实现这些手段的方法包括:偏向锁、轻量级锁、自旋锁、锁消除、锁膨胀等

1. 偏向锁

偏向锁是JDK1.6提出的一种锁优化方式。其核心思想是:如果程序没有竞争,则取消之前已经取得锁的线程同步操作。也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,无需再进行相关的同步操作,从而节省了操作时间。如果在此之间有其他线程进行了锁请求,则锁退出偏向模式。在JVM中使用-XX:+UseBiasedLocking 可以设置启用偏向锁。

偏向锁在锁竞争激烈的场合没有太强的优化效果。

2. 轻量级锁

如果偏向锁失败,Java虚拟机会让线程申请轻量级锁。轻量级锁在虚拟机内部,使用一个称为BasicObjecLock的对象实现,这个对象内部由一个BasicLock对象和一个持有该锁的Java对象指针组成。BasicobjectLock对象放置在Java栈的栈帧中。

首先,BasicLock通过set_displaced_header()方法备份了原对象的Mark Word。接着,使用CAS操作,尝试将BasicLock的地址复制到对象头的Mark Word。如果复制 成功,那么加锁成功。如果加锁失败,那么轻量级锁就有可能被膨胀为重量级锁。

3. 锁膨胀

当轻量级锁失败时,就会膨胀成重量级锁。轻量级锁加锁失败后,虚拟机会执行以下操作:1. 废弃前面BasicLock备份的对象头信息。2. 通过inflate()方法进行锁膨胀,其目地是获得对象的ObjectMonitor  3. 使用enter()方法尝试进入锁。

4. 自旋锁

锁膨胀后,进入ObjectMonitor的enter(),线程很可能会在操作系统层面被挂起,这样线程上下文切换的性能损失就比较大。因此,在锁膨胀之后,虚拟机会做最后的争取,希望线程可以尽快进入临界区而避免被操作系统挂起。一种较为有效的手段就是使用自旋锁。

自旋锁可以使线程在没有取得锁时,不被挂起,而转去执行一个空循环(即所谓的自旋),在若十个空循环后,线程如果可以获得锁,则继续执行。若依然不能获得锁,才会被挂起。不太适用于锁竞争激烈的场合。

在JDK 1.6中,Java虚拟机提供 -XX:+UseSpinning 参数来开户自旋锁,使用 -XX:PreBlockSpin 参数来设置自旋锁的等待次数。

在JDK1.7中,自旋锁参数被取消。自旋锁总是会执行,自旋次数也由虚拟机自行调整。

5. 锁消除

锁消除是Java虚拟机在JIT编译时,对运行上下文的扫描,运用逃逸技术,去除不可能存在共享资源竞争的锁。比如:

public void someBusiness(){
......
StringBuffer sb = new StringBuffer();
sb.append("XXX");
......
}

StringBuffer中的方法都是有synchronized的,但是这里只是方法内的局部变量,不可能存在锁竞争。

逃逸分析和锁消除分别可以使用参数 -XX:+DoEscapeAnalysis 和 -XX:+EliminateLocks 开启(锁消除必须工作在 -server模式下)

最新文章

  1. java基础-变量
  2. asp.net mvc本地程序集和GAC的程序集冲突解决方法
  3. zabbix自动发现监控url
  4. POJ 1511 最短路spfa
  5. JAVA EE 第一阶段项目问题
  6. Linux-Load blance
  7. utmp, wtmp, and lastlog 日志清除工具
  8. ETL几种方案对比
  9. 使用AjaxFileUpload.js实现文件异步上�
  10. OSPF理论总结
  11. c#实现windows远程桌面连接程序
  12. 实战-Mysql主从复制
  13. IIS加载JSON文件 错误 404
  14. Error Code: 1360 - Trigger does not existQuery
  15. 通过VirtualBox安装Linux系统(CentOS7)
  16. VS2013 添加控制台程序
  17. [转]SQL SERVER整理索引碎片测试
  18. [日常工作] SUSE设置上网ip地址
  19. C#字体与Rectangle简单对应关系
  20. PTA 7-2 符号配对(20 分)

热门文章

  1. linux install beanstalkd
  2. poj 2336 Ferry Loading II ( 【贪心】 )
  3. java入门了解05
  4. oracle数据库用户创建删除以及数据导入
  5. js中的window.open返回object的错误
  6. HDU 4336 Card Collector:状压 + 期望dp
  7. Java企业微信开发_12_异常:java.lang.OutOfMemoryError: Java heap space
  8. linux命令学习笔记(47):iostat命令
  9. Unity-2017.2官方实例教程Roll-a-ball(一)
  10. HDU5875Function(单调队列)