synchronized锁及其锁升级
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人。
文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。
多线程加锁有两种方式
- 利用Sychronized关键字
- 利用Lock接口子类ReentrantLock类
Sychronized关键字与Lock接口比较
- sychronized是java内置的关键字,查看不到线程是否获取到了锁;Lock接口是一个java接口,可以查看是否获取到了锁
- synchronized可以加在方法、代码块上;Lock接口写在代码里;
- synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
- synchronized加在方法、代码块上,同一时刻只能有一个线程使用这段代码,其他线程必须等待,并且其他线程不能响应中断(响应中断=中断等待的状态:将线程从等待状态变为就绪状态,以便线程能继续往下执行代码;线程响应中断后会抛出一个异常,业务代码必须手动处理该异常);而Lock接口可以响应中断
- Lock接口必须手动调用unlock()释放锁,否则容易造成死锁想象,一般在finally中调用unlock();
synchronized放弃锁只有两种情况:
(1)线程执行完了同步代码块的内容
(2)发生异常;而lock不同,它可以设定超时时间,也就是说他可以在获取锁时便设定超时时间,如果在你设定的时间内它还没有获取到锁,那么它会放弃获取锁然后响应中断操作。 - lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
synchronized锁升级
基础知识
每个【锁=锁对象】的对象头由两部分组成:Classpointer+Markword
(1)Classpointer=对象类型指针,JVM就是通过它来确定当前对象是属于哪个class实例
(2)Markword,32位的jvm中Markword是占4B=4byte=32b=32位,存放对象运行时的数据(对象gc时的分代年龄,对象hashcode,当前锁为偏向锁时的线程ID),synchronized锁机制与32位中的最后3位(1+2)密切相关,最后2位是普通锁位,倒数第三位是偏向锁位:

当锁对象被创建出来,此时锁对象为无锁状态,(偏向锁位,普通锁位)=(0,01),所有无锁对象都是可偏向的,即可以被任意线程加偏向锁,当第一个线程对该锁对象加锁时,会把偏向锁位由0变1代表偏向锁生效,同时把线程ID插入锁对象头的Markword中
synchronized锁升级的过程(无锁->...->重量级锁)
锁膨胀的过程:无锁(没有线程)->偏向锁(1个线程)->轻量级锁(有第二个及以上的线程竞争锁)->重量级锁(有三个及以上的线程竞争锁)
偏向锁
如何加锁:线程A第一次访问同步代码块中的代码时,先检查当前锁是否可偏向(偏向锁位为0),是则通过CAS获取锁,获取锁之后会在synchronized关键字对应的锁对象的对象头中,在Markword里记录本线程ID,线程A再次访问该同步代码块中的代码时,直接比较锁对象头的Markword的线程ID是否是本线程ID,若是则线程A可重入取锁进而直接访问同步代码块,否则说明是另外一个线程B想访问同步代码块,从而B竞争同一个【锁=锁对象】,此时锁升级
如何锁升级为轻量级锁:当线程B想访问synchronized同步代码块时,会检查synchronized关键字对应的锁对象的对象头中,Markword中线程ID是否为线程B的ID,若不是则B再检查锁对象头中记录的线程A是否还存活,不存活则直接把锁对象先置为无锁状态,再获取锁使其变为偏向锁;若存活则先暂停线程A,撤销偏向锁,再把【锁=锁对象】升级为轻量级锁,然后B线程自旋(不断循环调用cas获取锁,自旋会消耗cpu使得cpu空转,所以自旋有次数限制)
轻量级锁
如何升级为重量级锁:B线程在访问同步代码块时发现A线程正在占用锁对象,故把【锁=锁对象】升级为轻量级锁,然后B自旋了,这时又有C线程来,此时轻量级锁升级为重量级锁,同时除了得到锁的那个线程,其他线程均会被阻塞
synchronized由无锁状态膨胀为重量锁的特点
- jvm默认延迟4s后才开启偏向锁,在这4s期间的(锁=锁对象)又叫匿名偏向锁,4s后才记录得到锁的线程,可通过【-XX:BiasedLockingStartUpDelay=0】取消延时,可通过【-XX:-UseBiasedLocking = false】设置不要偏向锁
- 除了偏向锁可以降为无锁状态,其他锁只能升级,不能降级
- 偏向锁和轻量级锁在用户态维护,而重量级锁在内核态维护
OK,如果文章哪里有错误或不足,欢迎各位留言。
创作不易,各位的「三连」是二少创作的最大动力!我们下期见!
synchronized锁及其锁升级的更多相关文章
- Synchronized锁性能优化偏向锁轻量级锁升级 多线程中篇(五)
不止一次的提到过,synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的 尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchro ...
- java架构之路(多线程)synchronized详解以及锁的膨胀升级过程
上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...
- 关于Synchronized的偏向锁,轻量级锁,重量级锁,锁升级过程,自旋优化,你该了解这些
前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized(如有不懂请移至传送门,关于Synchronized的偏向锁,轻量级锁,重量级锁,锁升级过程,自旋优 ...
- synchronized中锁是怎么升级的
在JDK1.6以前,使用synchronized就只有一种方式即重量级锁,而在JDK1.6以后,引入了偏向锁,轻量级锁,重量级锁,来减少竞争带来的上下文切换. 锁升级主要依赖对象头中的Mark Wor ...
- synchronized和 synchronized 了解偏向锁、轻量级锁、重量级锁的概念以及升级机制、以及和ReentrantLock的区别。
并发 synchronized 了解偏向锁.轻量级锁.重量级锁的概念以及升级机制.以及和ReentrantLock的区别. https://www.cnblogs.com/deltadeb ...
- Synchronized关键字和锁升级,详细分析偏向锁和轻量级锁的升级
原文链接:https://blog.csdn.net/tongdanping/article/details/79647337 1.锁升级锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态 ...
- 线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)
接触过线程安全的同学想必都使用过synchronized这个关键字,在java同步代码快中,synchronized的使用方式无非有两个: 通过对一个对象进行加锁来实现同步,如下面代码. synchr ...
- synchronized底层实现原理&CAS操作&偏向锁、轻量级锁,重量级锁、自旋锁、自适应自旋锁、锁消除、锁粗化
进入时:monitorenter 每个对象有一个监视器锁(monitor).当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:1 ...
- 【转载】Java中的锁机制 synchronized & 偏向锁 & 轻量级锁 & 重量级锁 & 各自优缺点及场景 & AtomicReference
参考文章: http://blog.csdn.net/chen77716/article/details/6618779 目前在Java中存在两种锁机制:synchronized和Lock,Lock接 ...
随机推荐
- python3 爬虫 Scrapy库学习1
1生成项目:生成项目文件夹 scrapy startproject 项目名 2生成爬虫文件 scrapy genspider 爬虫名 指定域名 3进入items文件可以输入自己想要爬取的内容比如 te ...
- dfs:10元素取5个元素的组合数
#include "iostream.h" #include "string.h" #include "stdlib.h" int sele ...
- vue中TinyMCE图片 “data-mce-src” 属性的问题
1.问题 在使用Vue中使用TinyMCE富文本编辑器时,上传的图片除了src属性还会多出来个"data-mcee-src" 属性,而保存时实际也是保存的"data-mc ...
- 你对 Spring Boot 有什么了解?
事实上,随着新功能的增加,弹簧变得越来越复杂.如果必须启动新的 spring 项 目,则必须添加构建路径或添加 maven 依赖项,配置应用程序服务器,添加 spring 配置.所以一切都必须从头开始 ...
- HTML 5的页面结构和HTML 4或早先的HTML有什么不同?
一个典型的Web页面有页眉(header),页脚(footer),导航(navigation),正文(central area)和侧栏(side bar).现在如果是在HTML 4中,HTML部分中的 ...
- Linux运维最常用150个命令
线上查询及帮助命令(2个) man 查看命令帮助,命令的词典,更复杂的还有info,但不常用. help 查看Linux内置命令的帮助,比如cd命令. 文件和目录操作命令(18个) ls 全拼list ...
- 深入理解FIFO(包含有FIFO深度的解释)
FIFO: 一.先入先出队列(First Input First Output,FIFO)这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令. 1.什么是FIFO? FIFO是 ...
- 我的python学习记04
列表,元组,字典的使用一.列表列表的格式:list[元素1,元素2,--]列表也是一个有序集合,下标索引从0开始与字符串类似1.在列表中添加数据append:list.append(添加元素) (在最 ...
- Idea运行时Scala报错Exception in thread "main" java.lang.NoSuchMethodError:com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
一.情况描述 使用idea +scala+spark,运行程序代码如下: package cn.idcast.hello import org.apache.spark.rdd.RDD import ...
- java中StringTokenizer的用法
4.StringTokenizer StringTokenizer可以解析分隔符不是空格的情况.例子:import java.util.StringTokenizer;public class Tes ...