点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人。

文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。

多线程加锁有两种方式

  • 利用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锁及其锁升级的更多相关文章

  1. Synchronized锁性能优化偏向锁轻量级锁升级 多线程中篇(五)

    不止一次的提到过,synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的 尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchro ...

  2. java架构之路(多线程)synchronized详解以及锁的膨胀升级过程

    上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...

  3. 关于Synchronized的偏向锁,轻量级锁,重量级锁,锁升级过程,自旋优化,你该了解这些

    前言 相信大部分开发人员,或多或少都看过或写过并发编程的代码.并发关键字除了Synchronized(如有不懂请移至传送门,关于Synchronized的偏向锁,轻量级锁,重量级锁,锁升级过程,自旋优 ...

  4. synchronized中锁是怎么升级的

    在JDK1.6以前,使用synchronized就只有一种方式即重量级锁,而在JDK1.6以后,引入了偏向锁,轻量级锁,重量级锁,来减少竞争带来的上下文切换. 锁升级主要依赖对象头中的Mark Wor ...

  5. synchronized和 synchronized 了解偏向锁、轻量级锁、重量级锁的概念以及升级机制、以及和ReentrantLock的区别。

    并发 synchronized 了解偏向锁.轻量级锁.重量级锁的概念以及升级机制.以及和ReentrantLock的区别.       https://www.cnblogs.com/deltadeb ...

  6. Synchronized关键字和锁升级,详细分析偏向锁和轻量级锁的升级

    原文链接:https://blog.csdn.net/tongdanping/article/details/79647337 1.锁升级锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态 ...

  7. 线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)

    接触过线程安全的同学想必都使用过synchronized这个关键字,在java同步代码快中,synchronized的使用方式无非有两个: 通过对一个对象进行加锁来实现同步,如下面代码. synchr ...

  8. synchronized底层实现原理&CAS操作&偏向锁、轻量级锁,重量级锁、自旋锁、自适应自旋锁、锁消除、锁粗化

    进入时:monitorenter 每个对象有一个监视器锁(monitor).当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:1 ...

  9. 【转载】Java中的锁机制 synchronized & 偏向锁 & 轻量级锁 & 重量级锁 & 各自优缺点及场景 & AtomicReference

    参考文章: http://blog.csdn.net/chen77716/article/details/6618779 目前在Java中存在两种锁机制:synchronized和Lock,Lock接 ...

随机推荐

  1. Linux C++ 实现一个简易版的ping (也就是imcp协议)

    背景: 想实现一个在没外网的时候就自动重启路由器的功能. 又不想用ping命令,因为在代码里调用system("ping"); 可能会比较耗时,得单开线程.于是找了个实现ICMP协 ...

  2. TypeScript编译tsconfig.json配置

    配置预览 { "include": ["src/**/*"], "exclude": ["ndoe_modules", ...

  3. String s = "Hello";s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?

    没有.因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象.在这段代码中,s原先指向一个String对象,内容是 "Hello",然后我们对s进行 ...

  4. scrapy基于请求传参实现深度爬取

    请求传参实现深度爬取 请求传参: 实现深度爬取:爬取多个层级对应的页面数据 使用场景:爬取的数据没有在同一张页面中 在手动请求的时候传递item:yield scrapy.Request(url,ca ...

  5. SpringDataJpa备忘录

    单向多对一关系 //产品类型 一的一方 @Entity public class ProductDir { @Id @GeneratedValue private Long id; private S ...

  6. OpenCV+QT5在Window下的环境配置记录

    在安装OpenCV时最需要注意的是,OpenCV库,也就是我们需要的dll和动态库需要我们使用CMake来生成. 虽然在官网上下载得到的文件中已经包含了库文件和.h等头文件,但是在具体开发中编译器编译 ...

  7. 重定向(redirect)与转发(forward)的区别

    重定向(redirect)与转发(forward)的区别 1.重定向时地址栏会发生改变,转发时地址栏不会发生改变 当浏览器请求资源时,服务器直接访问目标地址的URL,将URL的响应内容读取,之后再将读 ...

  8. TOGAF D阶段:技术架构

    11. Phase D: Technology Architecture (opengroup.org) Phase D: Technology Architecture D阶段:技术架构 11.1 ...

  9. React-简单通用的抛物线动画

    一个简单通用的 React 抛物线动画demo Usage import { parabola } from "./parabola" ... onAnimate = () =&g ...

  10. .NET程序设计实验三

    实验三  Windows 应用程序开发 一.实验目的 1. 掌握窗口控件的使用方法: 2. 掌握Windows 的编程基础. 二.实验要求 根据要求,编写 C#程序,并将程序代码和运行结果写入实验报告 ...