Syncronized解析

作用:

)确保线程互斥的访问同步代码

)保证共享变量的修改能够及时可见

)有效解决重排序问题。

用法:

)修饰普通方法(锁是当前实例对象)

)修饰静态方法(锁是当前对象的Class对象)

)修饰代码块(锁是Synchonized括号里配置的对象)

底层实现原理:

方法和代码块都是基于进入和退出Monitor对象来实现方法同步和代码块同步,但两者的实现细节不一样。

(1)代码块同步是使用monitorenter和monitorexit指令实现,monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处

每个对象有一个监视器锁(monitor)。线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

,该线程即为monitor的所有者。

、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.

,再重新尝试获取monitor的所有权。

执行monitorexit的线程必须是锁对象所对应的monitor的所有者。

,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个
monitor 的所有权。

(2)方法同步是使用ACC_SYNCHRONIZED标示符实现的

相对于普通方法,常量池中多了ACC_SYNCHRONIZED标示符。当方法调用时,将会检查方法的
ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。

讲jdk1.6锁优化前的前置知识



锁的状态保存在java对象头中,那对象头是什么?

块区域:对象头、实例数据、对齐补充。(jvm知识)

对象头结构如下:

CAS:Compare and Swap,比较并设置。用于在硬件层面上提供原子性操作。比较是否和给定的数值一致,如果一致则修改,不一致则不修改。

Synchronized在jdk1.6的优化



Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex
Lock(互斥锁)来实现的,这个成本非常高,这就是为什么Synchronized效率低的原因。因此,这种依赖于操作系统Mutex Lock所实现的锁我们称之为“重量级锁”。JDK中对Synchronized做的种种优化,其核心都是为了减少这种重量级锁的使用。JDK1.6以后,为了减少获得锁和释放锁所带来的性能消耗,提高性能,引入了“轻量级锁”和“偏向锁”。

锁的状态总共有四种:

1.重量级锁(依赖操作系统的互斥锁)

2.轻量级锁(在无竞争的情况下使用CAS操作去消除同步使用的互斥量,默认开始就是这个)

3.偏向锁(在无竞争的情况下把整个同步都消除掉,连CAS操作都不做了)

4.无锁状态

随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁(但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级)

位的JDK为例:

无锁和重量级(操作系统的互斥锁)不用解释了,重点解释轻量级锁和偏向锁。

轻量级锁

时,膨胀为重量级锁。

轻量级锁解锁:轻量级解锁时,会使用原子的CAS操作来将栈帧中DisplacedMark Word替换回到对象头,如果成功,则表示没有竞争发生。如果失败,表示当前锁存在竞争,锁就会膨胀成重量级锁。

偏向锁

,偏向模式。

偏向锁加锁过程:

当锁对象第一次被线程获取的时候,虚拟机将会把对象头中的标志位设为“01”,即偏向模式。同时使用CAS操作把获取到这个锁的线程的ID记录在对象的Mark
Word之中,如果CAS操作成功,持有偏向锁的线程以后每次进入这个锁相关的同步块时,虚拟机都可以不再进行任何同步操作

偏向锁的撤销:

当有另外一个线程去尝试获取这个锁时,偏向模式就宣告结束。 根据锁对象目前是否处于被锁定的状态,撤销偏向(Revoke Bias)后恢复到未锁定(标志位为“01”)或轻量级锁定(标志位为“00”)的状态,后续的同步操作就如上面介绍的轻量级锁那样执行

三种锁状态的总结

相关的扩展:

1.  Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。

2.上文提到的偏向锁、轻量级锁都是jdk1.5到1.6的锁优化技术中的。锁优化技术还有如下:

适应性自旋:

互斥同步对性能最大的影响是阻塞的实现,因为挂起线程和恢复线程都是OS内核态完成的。那么使用自旋(即忙循环等待),不去阻塞地等待,这就是自旋锁技术。然而,自旋需要占用CPU时间,时间短还好,时间长了浪费性能,而适应性地根据同一个锁上的自旋时间及锁的拥有者状态决定时间,就是适应性自旋技术。

锁消除:

即时编译期运行时,有些代码上的同步,被检测到不可能存在数据竞争的锁,进行消除。检测依据来源于逃逸分析技术。

锁粗化:

如果一个方法里有A、B、C三句代码,都分别进行了三次Synchronized(this),其实没必要,反而增加了加锁解锁的消耗,这种情况会直接粗化为一个大Synchronized。

参考:

《深入理解Java虚拟机》

《Java并发编程艺术》

http://www.cnblogs.com/paddix/p/5405678.html

http://ifeve.com/java-synchronized/

Java并发编程总结(一)Syncronized解析的更多相关文章

  1. Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  2. (转)Java并发编程:volatile关键字解析

    转:http://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或 ...

  3. Java并发编程:volatile关键字解析(转载)

    转自https://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析   Java并发编程:volatile关键字解析 ...

  4. Java并发编程:volatile关键字解析-转

    Java并发编程:volatile关键字解析 转自海子:https://www.cnblogs.com/dayanjing/p/9954562.html volatile这个关键字可能很多朋友都听说过 ...

  5. Java并发编程中的设计模式解析(二)一个单例的七种写法

    Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ...

  6. Java并发编程:volatile关键字解析(学习总结-海子)

    博文地址:Java并发编程:volatile关键字解析

  7. 6、Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  8. 转:Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字, ...

  9. [转载]Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  10. 干货:Java并发编程必懂知识点解析

    本文大纲 并发编程三要素 原子性 原子,即一个不可再被分割的颗粒.在Java中原子性指的是一个或多个操作要么全部执行成功要么全部执行失败. 有序性 程序执行的顺序按照代码的先后顺序执行.(处理器可能会 ...

随机推荐

  1. Android 网络通信框架Volley(一)

    转自:http://blog.csdn.net/t12x3456/article/details/9221611 1. 什么是Volley 在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫 ...

  2. STL 补档

    STL 补档 1.vector 作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据. vector在C++标准模板库中的部分内容,它是 ...

  3. apache ignite系列(三):数据处理(数据加载,数据并置,数据查询)

    ​ 使用ignite的一个常见思路就是将现有的关系型数据库中的数据导入到ignite中,然后直接使用ignite中的数据,相当于将ignite作为一个缓存服务,当然ignite的功能远不止于此,下面以 ...

  4. 关于纯xmlhttprequest请求服务器数据

    今天我们的web技术已经相当的完善, 各种前端框架如jquery或者再深一点的工具APIcloud 的使用极大的方便了我们的开发工作. 今天我要分享一个纯javascript的方式来解决请求服务器数据 ...

  5. 表达式树练习实践:C# 循环与循环控制

    目录 表达式树练习实践:C# 循环 LabelTarget for / while 循环 无限循环 最简单的循环 多次循环 break 和 continue 一起 表达式树练习实践:C# 循环 C# ...

  6. MOOC 数据库系统笔记(二):数据库系统的基本结构及其演变发展

    数据库系统的结构抽象与演变 数据库的标准结构 DBMS管理数据的三个层次 1.External Level = User Level 某一用户能够看到与处理的数据,全局数据中的某一部分 2.Conce ...

  7. 【PyTorch】Tricks 集锦

    声明:本文大部分内容是从知乎.博客等知识分享站点摘录而来,以方便查阅学习.具体摘录地址已在文章底部引用部分给出. 1. 查看模型每层输出详情 from torchsummary import summ ...

  8. JavaScript之对象基础

    现实世界是由无数的事物或对象组成,事物都有各独特的属性和一些动作行为,一般我们可以通过事物的某些特征或行为动作描述它.JavaScript中也是如此,JavaScript对象是多个键值对的集合,键我们 ...

  9. Scala Basis

    基础 Scala 中数据类型也是 class 7 种数值类型: Byte, Char, Short, Int, Long, Float, and Double Boolean 类型 原始类型与 cla ...

  10. 先森林后树木:Elasticsearch各版本升级核心内容必看

    在学习Elasticsearch 时候,因为各个版本的问题,搞不清,非常的头疼,官方也给出了各个版本更新的情况,不过是英文版本,版本更新信息又特别多,最近学习,看了很多资料,没有一个整理很清楚的,然后 ...