synchronized 的实现方式是用 Monitor 进行加锁,这是一种互斥锁,为了表示他对性能的影响我们称之为重量级锁。

Java 的线程是映射到操作系统原生线程之上的,要阻塞或唤醒一个线程就需要操作系统的协助,让线程从用户态转换到内核态,而状态转换需要耗费 CPU 很多的时间。

锁优化仅在 Java 虚拟机 server 模式下起作用

自旋锁

Java 虚拟机的开发工程师们在分析过大量数据后发现:共享数据的锁定状态一般只会持续很短的一段时间,为了这段时间去挂起和恢复线程其实并不值得。

自旋锁在 JDK 1.4 中引入,在 JDK 1.6 中默认开启。

自旋等待虽然避免了线程切换的开销,但自旋的线程要占用处理器时间的,所以若锁被占用的时间很短,自旋等待的效果就会非常好,反之锁被占用的时间很长,那么自旋的线程只会白白消耗 CPU 资源。

因此自旋等待的时间必须要有一定的限度,超过限定的次数仍然没有成功获得锁,就应当挂起(阻塞)线程了。自旋次数的默认值是 10 次。

自适应自旋

在 JDK 1.6 中引入了自适应自旋锁。

自适应意味着自旋的时间不再固定了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。

如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也很有可能再次成功,进而它将允许自旋等待持续相对更长的时间,比如100个循环。

如果对于某个锁,自旋很少成功获得过,那在以后要获取这个锁时将可能省略掉自旋过程,以避免浪费处理器资源。

锁消除

在动态编译同步块的时候,JIT 编译器可以借助一种被称为逃逸分析(Escape Analysis)的技术来判断同步块所使用的锁对象是否只能够被一个线程访问而没有被发布到其他线程。从而取消对这部分代码的同步。

// 实际代码,hollis 的引用不会“逃逸”到 f()方法之外,其他线程无法访问到它,锁也就没有了意义
public void f() {
Object hollis = new Object();
synchronized(hollis) {
System.out.println(hollis);
}
}
// JIT 编译后代码
public void f() {
Object hollis = new Object();
System.out.println(hollis);
} // 和上面例子相同,sb 的作用域其他线程无法访问,append 方法的同步会被 JIT 编译消除掉
public String concatString(String s1, String s2, String s3) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
sb.append(s3);
return sb.toString();
}

锁粗化

当 JIT 编译器发现一系列连续的操作都对同一个对象反复加锁和解锁,甚至加锁操作出现在循环体中的时候,会将加锁同步的范围扩散(粗化)到整个操作序列的外部。

在编写代码的时候,总是推荐将同步块的作用范围(锁粒度)限制得尽量小(只在共享数据的实际作用域中才进行同步),这样是为了使得需要同步的操作数量尽可能变小,如果存在锁竞争,那等待锁的线程可以尽快的拿到锁。

锁粒度:不要锁住一些无关的代码。锁粗化:可以一次执行完的不要多次加锁执行

public Object object = new Object();
// 源代码
public void f() {
for (int i = 0; i < 100000; i++) {
synchronized (object) {
System.out.println("xx");
}
}
}
// JIT 编译后代码
public void f() {
synchronized (object) {
for (int i = 0; i < 100000; i++) {
System.out.println("xx");
}
}
} public StringBuffer sb = new StringBuffer();
// 和上面例子一样,会把 append 操作的锁提到上一层,让三个 append 操作只加一次锁
public String concatString(String s1, String s2, String s3) {
sb.append(s1);
sb.append(s2);
sb.append(s3);
return sb.toString();
}

https://www.jianshu.com/p/f05423a21e78


https://www.hollischuang.com/archives/2344

https://icyfenix.iteye.com/blog/1018932

Java-JVM 锁优化的更多相关文章

  1. 深入理解JVM(③)Java的锁优化

    前言 从JDK5到JDK6HotSpot虚拟机开发团队花费了大量的资源实现了各种锁优化技术,如适应性自旋(Adaptive Spinning).锁消除(Lock Elimination).锁膨胀(Lo ...

  2. 面试官:JVM锁优化都优化了啥?

    从JDK1.6开始,JVM对锁进行了各种优化,目的就是为了在线程间更高效的共享数据和解决互斥同步的问题.从锁优化的话题开始,可以引申出很多考点面试题,比如锁优化的技术.各优化技术的细节.CAS实现原理 ...

  3. Java的锁优化

    高效并发是从JDK 1.5到JDK 1.6的一个重要改进,HotSpot虚拟机开发团队在这个版本上花费了大量的精力去实现各种锁优化技术,如适应性自旋(Adaptive Spinning).锁消除(Lo ...

  4. JVM锁优化

    1. 概述 JDK1.6版本花费了大量精力去实现各种锁优化,如适应性自旋,锁消除,锁粗化,轻量级锁,偏向锁等,这些技术都是为了在线程期间更高效的共享数据,以及解决竞争问题. 2. 自旋锁与自适应自旋 ...

  5. JVM锁优化以及区别

    偏向所锁,轻量级锁都是乐观锁,重量级锁是悲观锁. 首先简单说下先偏向锁.轻量级锁.重量级锁三者各自的应用场景: 偏向锁:只有一个线程进入临界区: 轻量级锁:多个线程交替进入临界区: 重量级锁:多个线程 ...

  6. B5. Concurrent JVM 锁优化

    [概述] 高效并发是从 JDK1.5 到 JDK 1.6 的一个重要改进,HotSpot 虚拟机开发团队在这个版本上花费了大量的精力去实现各种锁优化技术,如适应性自旋(Adaptive Spining ...

  7. Java 多线程 - 锁优化

    http://www.cnblogs.com/pureEve/p/6421273.html https://www.cnblogs.com/mingyao123/p/7424911.html

  8. 百万并发中间件系统的内核设计看Java并发性能优化

    “ 这篇文章,给大家聊聊一个百万级并发的中间件系统的内核代码里的锁性能优化. 很多同学都对Java并发编程很感兴趣,学习了很多相关的技术和知识.比如volatile.Atomic.synchroniz ...

  9. java源码剖析: 对象内存布局、JVM锁以及优化

    一.目录 1.启蒙知识预热:CAS原理+JVM对象头内存存储结构 2.JVM中锁优化:锁粗化.锁消除.偏向锁.轻量级锁.自旋锁. 3.总结:偏向锁.轻量级锁,重量级锁的优缺点. 二.启蒙知识预热 开启 ...

  10. 使用ZooKeeper实现Java跨JVM的分布式锁(优化构思)

    一.使用ZooKeeper实现Java跨JVM的分布式锁 二.使用ZooKeeper实现Java跨JVM的分布式锁(优化构思) 三.使用ZooKeeper实现Java跨JVM的分布式锁(读写锁) 说明 ...

随机推荐

  1. jQuery遍历(1)

    jQuery 遍历,意为“移动”,用于根据其相对于其他元素的关系来“查找”(或选取)HTML 元素.以某项选择开始,并沿着这个选择移动,直到抵达您期望的元素为止. 图示解释: 举例: jQuery p ...

  2. [#Linux] CentOS 7 禁用笔记本的触摸板

    安装 xorg-x11-apps yum install xorg-x11-apps 查看对应设备的 id xinput –list 关闭 touchpad xinput set-int-prop 1 ...

  3. Android笔记(五) Activity的启动模式

    Android中Activity是由返回栈来管理的,在默认情况下,每当启动一个新的Activity,它都会在返回栈中入栈,并且出于栈的顶端.但是有些时候Activity已经在栈的顶端了,也就不需要再启 ...

  4. [Docker][ansible-playbook]3 持续集成环境之分布式部署

    预计阅读时间: 30分钟 本期解决痛点如下:1. 代码版本的多样性,编译环境的多样性如何解决?答案是使用docker,将不同的编译环境images统统打包到私有仓库上,根据需求进行下载,从宿主机上挂载 ...

  5. Castle.Windsor依赖注入的高级应用与生存周期

    1. 使用代码方式进行组件注册[依赖服务类] using System; using System.Collections.Generic; using System.Linq; using Syst ...

  6. js onclick事件传参

    传字符串参数 var html = "<a href='#' onclick='onedit(""+ row.name + "")';>编 ...

  7. 中文日历Calendar

    一.层次结构 Object<-----Calendar<-----EastAsianLunisolarCalendar<-----ChineseLunisolarCalendar(农 ...

  8. PL/SQL嵌入SQL语句

    一.PL/SQL块中只能直接嵌入SELECT.DML(INSERT,UPDATE,DELETE)以及事务控制语句(COMMIT,ROLLBACK,SAVEPOINT), 而不能直接嵌入DDL语句(CR ...

  9. selenium.webdriver获取结果转为json格式

    from selenium import webdriver driver.get(requestUrl)html = driver.page_sourcesoup = BeautifulSoup(h ...

  10. css 移动端页面,在ios中,margin-bottom 没有生效

    在开发中,你会遇到各种美轮美奂的UI交互设计图,下面这种UI图,我在开发时就在布局上遇到一个小问题 问题现象:ios 手机滚动到底部,底部的margin-bottom不生效,Android手机和模拟器 ...