JDK内部的“锁”优化策略

1. 锁偏向

  锁偏向是针对加锁操作的优化手段,核心思想是:如果一个线程获得了锁,那么锁就进入偏向模式,当这个线程再次请求锁时,无须再做任何同步操作,这样就节省了大量有关锁申请的操作,从而提高了程序的性能。对几乎没有锁竞争的场合,偏向锁有很好的优化效果,对于锁竞争激烈的场合,效果不佳,因为每次都是不同的线程在申请锁,偏向模式就会失效,还不如不启用偏向锁。使用Java虚拟机参数 -XX:+UseBiasedLocking 可以开启偏向锁。

2. 轻量级锁

  如果偏向锁失败,虚拟机不会立即挂起线程,会使用一种轻量级锁的优化手段。就是简单地将对象头部作为指针指向持有锁的线程堆栈内部,来判断一个线程是否持有对象锁。如果线程获得轻量级锁成功,可以顺利进入临界区。如果轻量级加锁失败,其他线程已经抢到了锁,当前线程的锁请求会膨胀为重量级锁。

3. 自旋锁

  锁膨胀以后,为了避免线程真实地在操作系统层面挂起,虚拟机还会做最后努力--自旋锁。当前线程暂时无法获得锁,而且什么时候可以获得锁是未知数,也许在几个CPU时钟周期内就可以得到锁。系统会假设不久将来线程可以得到这把锁,因此,虚拟机会让当前线程做几个空循环,在经过若干次循环以后,如果可以得到锁,那么就顺利进入临界区。如果还不能得到锁,才会真的将线程在操作系统层面挂起。

4. 锁消除

  是一种更彻底的锁优化,Java虚拟机在JIT编译时,通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过锁消除,可以节省毫无意义的请求锁时间。例如在一个不可能存在并发竞争的场合使用Vector,但Vector内部使用了Synchronized请求锁,比如下面代码:

public String[] createStrings(){
Vector<String> v = new Vector<String>();
for(int i=0;i<100;i++){
v.add(Integer.toString(i));
}
return v.toArray(new String[0]);
}

  上述代码中Vector,由于变量v只在createStrings函数中使用,因此他只是一个单纯的局部变量。局部变量是在线程栈上分配的,属于线程私有的数据,因此不可能被其他线程访问。这样的情况下,Vector内部所有的加锁同步是没必要的。如果虚拟机检测到这种情况,就会将这些无用的锁操作去除。

  锁消除涉及的一项关键技术为逃逸分析。逃逸分析是观察某一个变量是否会逃出一个作用域。在本例中,变量v显然没有逃出createStrings()函数之外。以此为基础,虚拟机才可以大胆地将变量v内部的加锁操作去除。如果createStrings()返回的不是数组,而是v本身,那么就认为变量v逃逸出了当前函数,也就是说变量v有可能被其他线程访问。如果这样,虚拟机就不能消除变量v中的锁操作。

  逃逸分析必须在 -server 模式下进行,可以使用 -XX:+DoEscapeAnalysis 参数打开逃逸分析。使用 -XX:+EliminateLocks 参数可以打开锁消除。

多线程(7)— JDK对锁优化的努力的更多相关文章

  1. 并发设计模式和锁优化以及jdk8并发新特性

    1 设计模式 (1) 单例模式 保证一个类只能一个对象实现.正常的单例模式分为懒汉式和饿汉式,饿汉式就是把单例声明称static a=new A(),系统第一次调用的时候生成(包括调用该类的其他静态资 ...

  2. Java 虚拟机对锁优化所做的努力

    作为一款公用平台,JDK 本身也为并发程序的性能绞尽脑汁,在 JDK 内部也想尽一切办法提供并发时的系统吞吐量.这里,我将向大家简单介绍几种 JDK 内部的 "锁" 优化策略. 1 ...

  3. 深入理解多线程(五)—— Java虚拟机的锁优化技术

    本文是<深入理解多线程>的第五篇文章,前面几篇文章中我们从synchronized的实现原理开始,一直介绍到了Monitor的实现原理. 前情提要 通过前面几篇文章,我们已经知道: 1.同 ...

  4. Java虚拟机对锁优化所做的努力(读书笔记)

    锁偏向      是一种加锁操作的优化手段,他的核心思想是:如果一个线程获得了锁,那么就进入偏向模式,当这个线程再次请求锁时,无须在做任何同步操作,因此在几乎没有锁竞争的场合,偏向锁是比较好的优化效果 ...

  5. Java并发与多线程与锁优化

    前言 目前CPU的运算速度已经达到了百亿次每秒,所以为了提高生产率和高效地完成任务,基本上都采用多线程和并发的运作方式. 并发(Concurrency):是指在某个时间段内,多任务交替处理的能力.CP ...

  6. Java多线程编程—锁优化

    并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如 ...

  7. java多线程编程——锁优化

    并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如 ...

  8. Java多线程之锁优化策略

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561264.html  锁的优化策略 编码过程中可采取的锁优化的思路有以下几种: 1:减少锁持有时间 例如:对 ...

  9. Java多线程编程 — 锁优化

      阅读目录 一.尽量不要锁住方法 二.缩小同步代码块,只锁数据 三.锁中尽量不要再包含锁 四.将锁私有化,在内部管理锁 五.进行适当的锁分解 正文 并发环境下进行编程时,需要使用锁机制来同步多线程间 ...

随机推荐

  1. 用vue做的购物车结算的功能

    <!-- 占位 --> <template> <div> <div class="product_table"> <div c ...

  2. Java学习之"Hello World"

    好像学习每个程序敲的第一个代码都是"Hello World",而学习Java也不例外,这篇博客就讲一下我学习Java的第一个程序HelloWorld.java 程序代码: publ ...

  3. MQ消息机制如何确认消费了消息?

    消息队列如何保证消息能百分百成功被消费 目前常用的消息队列有很多种,如RabbitMQ,ActiveMQ,Kafka...下面以RabbitMQ为例来讲如何保证消息队列中的信息能百分百被消费掉. 其中 ...

  4. 【转】IDEA新建项目时,没有Spring Initializr选项(亲测有效)

    最近开始使用IDEA作为开发工具,然后也是打算开始学习使用spring boot.看着博客来进行操作上手spring boot,很多都是说创建一个新项目(Create New Project) 选择 ...

  5. Kubernetes addons 之 coredns部署

    Kubernetes addons 之 coredns部署 2019.06.04 18:04:35字数 1045阅读 121 DNS 是 Kubernetes 的核心功能之一,通过 kube-dns ...

  6. Android中jsoup的混淆规则【转】

    Android中jsoup的混淆规则版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com 说实话这篇文章的标题和内容我觉得很水,所以读者们要是也觉得这篇文章 ...

  7. docker 安装redis 并配置外网可以访问

    1, docker 拉去最新版本的redis docker pull redis #后面可以带上tag号, 默认拉取最新版本 2, docker安装redis container 安装之前去定义我们的 ...

  8. SQLServer系统视图sysobjects中type字段说明

    SQLServer中系统视图sysobjects中type字段的对象类型: AF = 聚合函数 (CLR) C = CHECK 约束 D = DEFAULT(约束或独立) F = FOREIGN KE ...

  9. mailgun php 邮件发送 实例

    步骤如下: 通过 composer 获取代码库 获取 API Key 以及 domain 编写代码发送邮件 1. 首先通过 composer 获取依赖代码库,参考官网给的命令 https://docu ...

  10. stl中map的四种插入方法总结

    stl中map的四种插入方法总结方法一:pair例:map<int, string> mp;mp.insert(pair<int,string>(1,"aaaaa&q ...