Java并发编程总结(一)Syncronized解析
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解析的更多相关文章
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- (转)Java并发编程:volatile关键字解析
转:http://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或 ...
- Java并发编程:volatile关键字解析(转载)
转自https://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 ...
- Java并发编程:volatile关键字解析-转
Java并发编程:volatile关键字解析 转自海子:https://www.cnblogs.com/dayanjing/p/9954562.html volatile这个关键字可能很多朋友都听说过 ...
- Java并发编程中的设计模式解析(二)一个单例的七种写法
Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ...
- Java并发编程:volatile关键字解析(学习总结-海子)
博文地址:Java并发编程:volatile关键字解析
- 6、Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- 转:Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字, ...
- [转载]Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- 干货:Java并发编程必懂知识点解析
本文大纲 并发编程三要素 原子性 原子,即一个不可再被分割的颗粒.在Java中原子性指的是一个或多个操作要么全部执行成功要么全部执行失败. 有序性 程序执行的顺序按照代码的先后顺序执行.(处理器可能会 ...
随机推荐
- (转载)非常完善的Log4net配置详细说明
一.前言 在项目中,对项目的日志收集是非常重要的,这里我就说说代码的异常日志收集.收集异常日志,有很多第三方成熟的框架,我这里就介绍一下我常用的Log4net. Log4Net介绍 Log4net 是 ...
- 完整剖析SpringAOP的自调用
摘要 spring全家桶帮助java web开发者节省了很多开发量,提升了效率.但是因为屏蔽了很多细节,导致很多开发者只知其然,不知其所以然,本文就是分析下使用spring的一些注解,不能够自调用的问 ...
- 新手学习FFmpeg - 调用API调整视频局部速率
通过修改setpts代码实现调整视频部分的播放速率. 完整代码可参考: https://andy-zhangtao.github.io/ffmpeg-examples/ 在前面提到了PTS/DTS/T ...
- Java,Python,前端,Linux,公众号等5T编程资源整理免费下载
场景 我的CSDN: https://blog.csdn.net/BADAO_LIUMANG_QIZHI 实现 马士兵Java学习视频 方立勋JavaWeb 尚硅谷Python核心基础 数据分析 机器 ...
- java 手机号码+邮箱的验证
import java.util.regex.Pattern; //导入的包 1:String REGEX_MOBILE = "^((17[0-9])|(14[0-9])|(13[0-9]) ...
- Java Synchronized Method This Static Class Object 区别
1. 必须基于对象 Synchronized Method 和 Synchronized(this) 块,除了范围小点 (方法和块),没差别都是阻塞整个对象 - 如果对象有多个 Synchronize ...
- mysql按关键词截取字符串
按关键字截取字符串 :substring_index(被截取字段,关键字,关键字出现的次数) eg:字符串:test.docx:test2.zip substring_index(file_name, ...
- mybatis中collection association优化使用及多参数传递
mybatis都会用,但要优雅的用就不是那么容易了 今天就简单举例,抛砖引玉,供大家探讨 1.主表 CREATE TABLE `test_one` ( `id` int(11) NOT NULL AU ...
- 词向量(one-hot/SVD/NNLM/Word2Vec/GloVe)
目录 词向量简介 1. 基于one-hot编码的词向量方法 2. 统计语言模型 3. 从分布式表征到SVD分解 3.1 分布式表征(Distribution) 3.2 奇异值分解(SVD) 3.3 基 ...
- python的元组存储的实质和多元赋值
python中有一种赋值机制即多元赋值,采用这种方式赋值时,等号两边的对象都是元组并且元组的小括号是可选的.通常形式为 x, y, z = 1, 2, 'a string' 等同于 (x, y, z) ...