上一篇文章介绍了synchronized的基本使用方法和实现,在实现部分说明了synchronized的底层实现依赖系统互斥锁mutex,但是这个一个重型锁,竞争导致线程阻塞挂起,后续拿到锁后再恢复线程,因为java使用的是1对1的线程模型,这个过程页涉及到了用户态和内核态的转换,比较消耗性能。为了解决这个问题,java1.6引入了“轻量级锁”、“偏向锁”。

1.锁优化

  锁的状态分为四种:无锁、偏向锁、轻量级锁,重量级锁,四种锁状态对性能的消耗依次增高,状态的转化也是由无锁向重量级锁转化,这个过程称之为锁的升级,不会出现锁的降级,除非解锁了向无锁状态转换,四种锁状态下对象头前32bit如下(以32bit为例)

锁状态

25 bit

4bit

1bit

2bit

23bit

2bit

是否是偏向锁

锁标志位

轻量级锁

指向栈中锁记录的指针

00

重量级锁

指向互斥量(重量级锁)的指针

10

GC标记

11

偏向锁

线程ID

Epoch

对象分代年龄

1

01

无锁

对象的hashCode

对象分代年龄

0

01

  锁状态转化如下图所示:

  基本的转化流程如下(详细可以参考:http://www.cnblogs.com/paddix/p/5405678.html):

  偏向所锁,轻量级锁都是乐观锁,重量级锁是悲观锁。
  一个对象刚开始实例化的时候,没有任何线程来访问它的时候。它是可偏向的,意味着,它现在认为只可能有一个线程来访问它,所以当第一个
线程来访问它的时候,它会偏向这个线程,此时,对象持有偏向锁。偏向第一个线程,这个线程在修改对象头成为偏向锁的时候使用CAS操作,并将
对象头中的ThreadID改成自己的ID,之后再次访问这个对象时,只需要对比ID,不需要再使用CAS在进行操作。
  一旦有第二个线程访问这个对象,因为偏向锁不会主动释放,所以第二个线程可以看到对象时偏向状态,这时表明在这个对象上已经存在竞争了,检查原来持有该对象锁的线程是否依然存活,如果挂了,则可以将对象变为无锁状态,然后重新偏向新的线程,如果原来的线程依然存活,则马上执行那个线程的操作栈,检查该对象的使用情况,如果仍然需要持有偏向锁,则偏向锁升级为轻量级锁,(偏向锁就是这个时候升级为轻量级锁的)。如果不存在使用了,则可以将对象回复成无锁状态,然后重新偏向。
  轻量级锁认为竞争存在,但是竞争的程度很轻,一般两个线程对于同一个锁的操作都会错开,或者说稍微等待一下(自旋),另一个线程就会释放锁。 但是当自旋超过一定的次数,或者一个线程在持有锁,一个在自旋,又有第三个来访时,轻量级锁膨胀为重量级锁,重量级锁使除了拥有锁的线程以外的线程都阻塞,防止CPU空转。
2.自旋锁、锁粗化和锁消除
  自旋锁和自适应自旋:从上图可以看到,轻量级锁就是一个自旋锁,当加锁的对象已经被加锁(轻量级锁加锁)的时候,当前线程自旋等待,直到获得锁或者锁升级。虚拟机会根据以往的自旋锁获得的情况,设置下次获取锁时自旋等待时间,如果上一次自旋锁加锁成功,会增加下一次自旋时间,如果上一次自旋锁加锁失败,会减少下一次自旋锁自旋时间。
  锁粗化:连续多个加锁、解锁操作导致性能下降,这是虚拟机会根据情况,将整个代码块一起同步,一次加锁解锁,降低性能消耗。
  锁消除:对于不需要同步的代码块,消除加锁解锁。主要基于逃逸技术分析,认为该代码块只会在当前线程访问,无需与其他线程同步,无需保证线程安全。
 
参考:
http://www.cnblogs.com/paddix/p/5405678.html
https://www.zhihu.com/question/53826114
《深入理解java虚拟机》

关于java的Synchronized,你可能需要知道这些(下)的更多相关文章

  1. Java 多线程 —— synchronized关键字

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  2. Java的synchronized关键字:同步机制总结

    JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...

  3. JAVA多线程synchronized详解

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 当两个并发线程访问同一个对象object中的这个synchronized(this)同 ...

  4. java中synchronized的用法详解

    记下来,很重要. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchron ...

  5. JAVA关键词synchronized的作用

    记下来,很重要. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchron ...

  6. java中synchronized的使用方法与具体解释

    Java语言的keyword.当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多仅仅有一个线程运行该段代码. 一.当两个并发线程訪问同一个对象object中的这个synchronized ...

  7. java同步synchronized

    java同步synchronized volatile仅仅用来保证该变量对所有线程的可见性,但不保证原子性. 看下面的这段代码: /** * * @author InJavaWeTrust * */ ...

  8. 理解java关键字Synchronized(学习笔记)

    之前学习了线程的一些相关知识,今天系统的总结下来 目录 1. Java对象在堆内存中的存储结构 2. Monitor管程 3. synchronized锁的状态变换以及优化 4. synchroniz ...

  9. java中synchronized关键字分析

    今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...

  10. Java 中 synchronized的用法详解(四种用法)

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.本文给大家介绍java中 synchronized的用法,对本文感兴趣的朋友一起看看吧 ...

随机推荐

  1. Struts(二十六):文件上传

    表单的准备 想要使用html表单上传一个或多个文件 1.须把html表单的enctype属性设置为multipart/form-data 2.须把html表单的method属性设置为post 3.须添 ...

  2. jquery楼层效果

  3. 使用Git简单笔记

    这里只是作为简单的笔记整理,第一次使用的推荐先看一下廖大的教程,内容很多很细,可以边看边练.看不懂的地方先记着.争取七七八八看下来. ================================= ...

  4. win7下ubuntu14.4双系统安装

    参考https://jingyan.baidu.com/article/f71d60379824041ab641d19d.html

  5. [LeetCode] Redundant Connection 冗余的连接

    In this problem, a tree is an undirected graph that is connected and has no cycles. The given input ...

  6. testng中使用reportng报告

    1.pom.xml文件中添加依赖,重构一下项目(mvn compile) <dependency> <groupId>org.uncommons</groupId> ...

  7. [BZOJ 5093]图的价值

    Description 题库链接 一个带标号的图的价值定义为每个点度数的 \(k\) 次方的和.给定 \(n\) 和 \(k\) ,请计算所有 \(n\) 个点的带标号的简单无向图的价值之和.对 \( ...

  8. hihocoder 1388 fft循环矩阵

    #1388 : Periodic Signal 时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal proce ...

  9. bzoj 2004: [Hnoi2010]Bus 公交线路

    Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距 离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决 ...

  10. POJ 3415 不小于k的公共子串的个数

    Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9248   Accepted: 3071 ...