前言

今天碰到一个synchronized锁升级的问题, 查了查, 发现一个帖子举例说明比较贴切, 特此转发, 如有问题, 欢迎讨论说明

转自: 木叶盒子 https://www.bilibili.com/read/cv15920091/

java提供两种锁:lock和synchronized,关于二者的区别,网上一个说法非常好:

synchronized相当于自动挡汽车,使用简单,可以覆盖大部分使用场景
但如果你想玩漂移等特殊操作,就需要lock,使用相对麻烦,但可以实现一些特殊场景,如公平锁

实际上二者出身就有本质区别,synchronized是官方的,而lock是民间的李二狗写出来的,起初刚开始lock无论在功能上还是性能上都超越了synchronized,可以说狠狠的打了官方的脸。

因此在1.5版本之后官方通过锁升级对synchronized的性能做了提升,本文主要简单介绍synchronized锁升级的过程

synchronized

ynchronized是一种对象锁(锁的是对象而非引用),作用粒度是对象,java中每个对象都可以上锁(同一时间只有一个线程能上锁成功),而且通过对象内部存储的markword标记锁状态。

synchronized加锁方式

  • 同步实例方法,锁是当前实例对象
  • 同步类方法,锁是当前类对象
  • 同步代码块,锁是括号里面的对象
public class Syc {
   Object lock = new Object();
   public synchronized static void go() {
// 锁的是Syc.class对象
   }
   public synchronized void say() {
// 锁的是Syc对象实例
}
  synchronized (lock) {
// 锁的是lock对象实例        
}    
}

锁升级

首先过一下synchronized锁升级的过程

1.偏向锁

当只有一个线程获得了锁,锁就进入偏向模式,MarkWord标识偏向状态,当这个线程再次请求锁时,无需再做任何同步操作,即获取锁的过程,这样就省去了大量有关锁申请的操作。

2.轻量级锁

当有其它线程要获取锁,竞争不是很激烈,锁进入轻量级锁,MarkWord标识轻量级状态,此时等待锁的线程开始自旋,即空循环等待锁释放,此过程不释放cpu。

3.重量级锁

当获取锁的竞争变的激烈,比如来了很多个线程或者某个线程自旋等待的次数太多了,锁进入重量级锁,MarkWord标识重量级状态,重量级锁依赖操作系统的Mutex lock实现,此时等待锁的线程挂起,当锁释放后再由操作系统唤醒重新尝试获取锁,由于借助操作系统,导致用户态内核态切换,此过程时间成本比较高。

原始的synchronized是直接使用重量级锁,才会导致性能很低,加入锁升级才使得synchronized性能获得很大提升。

理解

以上讲解了synchronized锁升级的过程,如果不好理解,还是拿现实生活举个例子:

假设某公司有多个会议室,每个团队需要获取到会议室的锁才能进去开会,会议室门口挂着一个写字板,时刻记录当前会议室使用状态。

  • 会议室相当于对象
  • 团队相当于线程
  • 会议室的锁相当于对象的锁
  • 写字板相当于MarkWord

1.偏向锁

公司发现大部分时间,同一个会议室都是同一个团队占用,于是当A团队第一次占用会议室时,在写字板上写上偏向 A团队,下次A团队进入不用修改就可以直接进入会议室,大大提升了开会效率。

如果B团队想使用会议室,此时A团队已经不使用该会议室,则修改写字板偏向 B团队。

这就是偏向锁,经过研究发现,在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,因此为了减少同一线程获取锁带来的开销,所以引入偏向锁。

2.轻量级锁

如果B团队想使用会议室,此时A还占用着会议室(写字板上记录偏向 A团队),此时出现了竞争,写字板上修改为轻量竞争,B团队哪也不去,就在会议室外原地打转(自旋)等着,因为公司大部分会议时间都很短,B相信A一般会很快出来。

如果A确实一会就出来了,B马上去抢会议室的锁。

这就是轻量级锁,偏向锁出现了竞争会升级为轻量级锁,因为大部分线程占用锁的时间不会特别长,所以等待线程刚开始不需要挂起,只需要通过空转自旋等待,一般很快就会获取到锁,比过程一直占用着cpu。

3.重量级锁

上面的情况,如果B等了很久A都不出来,或者这段时间公司特别繁忙,各团队频繁开会,还有C,D,E...等等团队也要使用该会议室,这时如果A在里面开会没完没了,其它团队一直在外面傻转着也不是事。

这时候就要请会议室管理员帮忙了,他让各团队都回去睡觉吧,写字板上修改为重量竞争,等A团队开完会出来,我负责通知其它团队,你们再过来抢会议室的锁。

这样在会议室竞争特别激烈时,请会议室管理员帮忙有效的避免了等待团队傻等,但如果在竞争不激烈的情况下就没有必要请出会议室管理员,毕竟造成额外开销,而且靠会议室管理员通知再来抢会议室肯定比站会议室外面等要慢很多。

这就是重量级锁,其中会议室管理员相当于操作系统,当某个线程自旋次数过多或者多个线程同时竞争锁,锁竞争变的激烈,轻量级锁升级为重量级锁,此时等待线程都挂起,对象锁释放后再由操作系统唤醒线程,此过程开销很大。

synchronized最开始就是不管竞争激不激烈都使用重量级锁导致性能很低,但竞争激励时如果任由等待线程空转消耗跟大,所以竞争激励升级为重量级锁也是非常合理。

其他

再补充几个问题

可重入锁

synchronized是一种可重入锁,比如有两个方法A,B锁的都是同一个对象,其中A调用B,那么某线程获取锁后进入A方法也能顺利进入B方法,即自己不会锁自己(否则synchronized修饰的方法都不能递归了),常用的ReentrantLock也是可重入锁。

公平/非公平

从上面的描述也会发现,当某个线程释放锁,其它线程会重新竞争锁,没有先来后到,就跟抢公交一样一拥而上,这就是不公平,我们的 synchronized就是一个非公平锁。

如果想实现公平锁,可以用ReentrantLock,他会维护一个队列,先到先得,就像排队上地铁,文明多了。

简单的理解synchronized锁升级的更多相关文章

  1. 再谈synchronized锁升级

    在图文详解Java对象内存布局这篇文章中,在研究对象头时我们了解了synchronized锁升级的过程,由于篇幅有限,对锁升级的过程介绍的比较简略,本文在上一篇的基础上,来详细研究一下锁升级的过程以及 ...

  2. Synchronized锁升级原理与过程深入剖析

    Synchronized锁升级原理与过程深入剖析 前言 在上篇文章深入学习Synchronized各种使用方法当中我们仔细介绍了在各种情况下该如何使用synchronized关键字.因为在我们写的程序 ...

  3. Synchronized锁升级

    Synchronized锁升级 锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁状态(级别从低到高) 为什么要引入偏向锁? 因为经过HotSpot的作者大量的研究发现,大多数时候是不存在锁竞 ...

  4. 详细了解 synchronized 锁升级过程

    前言 首先,synchronized 是什么?我们需要明确的给个定义--同步锁,没错,它就是把锁. 可以用来干嘛?锁,当然当然是用于线程间的同步,以及保护临界区内的资源.我们知道,锁是个非常笼统的概念 ...

  5. 深入并发锁,解析Synchronized锁升级

    这篇文章分为六个部分,不同特性的锁分类,并发锁的不同设计,Synchronized中的锁升级,ReentrantLock和ReadWriteLock的应用,帮助你梳理 Java 并发锁及相关的操作. ...

  6. synchronized锁升级详细过程

    java对象头由3部分组成: 1.Mark Word 2.指向类对象(对象的class对象)的指针 3.数组长度(数组类型才有) 重点是 Mark Word结构,下面以32位HotSpot为例: 一. ...

  7. 并发编程:synchronized 锁升级过程的验证

        关于synchronized关键字以及偏向锁.轻量级锁.重量级锁的介绍广大网友已经给出了太多文章和例子,这里就不再重复了,也可点击链接来回顾一下.在这里来实战操作一把,验证JVM是怎么一步一步 ...

  8. 【大厂面试07期】说一说你对synchronized锁的理解?

    synchronized锁的原理也是大厂面试中经常会涉及的问题,本文主要通过对以下问题进行分析讲解,来帮助大家理解synchronized锁的原理. 1.synchronized锁是什么?锁的对象是什 ...

  9. synchronized锁及其锁升级

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 多线程加锁有两种方式 利用Sychronized关键字 利用Lock接口 ...

  10. Synchronized锁及其膨胀

    一.序言 在并发编程中,synchronized锁因其使用简单,在线程间同步被广泛应用.下面对其原理及锁升级过程进行探究. 二.如何使用 1.修饰实例方法 当实例方法被synchronized修饰时, ...

随机推荐

  1. 3、k8s 核心实战

    7 kubernets核心实战 7.1 资源创建方式 命令行 yaml 7.2 namespace 名称空间来隔离资源 命令行方式 kubectl create ns hello kubectl de ...

  2. 5G工业智能网关助力智能制造开辟新赛道

    今年以来,物联网技术加速产业变革,制造业出现了不少新现象.从大规模到个性化.从"渠道为王"到"用户定义".从自有工厂到共享协同,智能化制造在很多地方颠覆了传统模 ...

  3. 一套.NET Core +WebAPI+Vue前后端分离权限框架

    今天给大家推荐一个基于.Net Core开发的企业级的前后端分离权限框架. 项目简介 这是基于.NetCore开发的.构建的简单.跨平台.前后端分离的框架.此项目代码清晰.层级分明.有着完善的权限功能 ...

  4. home条 防止误碰

    某些界面需要隐藏home条,防止误触导致页面返回 - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures { return UIRectEd ...

  5. C语言II博客作业04

    C语言II-作业04 作业头 这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/SE2020-2/?page=2 这个作业要求在哪里 https://ed ...

  6. ORACLE 失效索引重建

    -- 获取失效索引 SELECT * FROM USER_INDEXES WHERE TABLE_NAME IN ('表名') AND STATUS = 'UNUSABLE'; -- 重建语法alte ...

  7. 用telnet远程连接linux系统

    环境,centos7.6 通过telnet进行远程登录的方法如下: 1.安装telnet,telnet-server,xinetd 检测是否安装telnet rpm -qa | grep telnet ...

  8. Google colab防断联

    (1)进入Colab的notebook界面,按快捷键F12,打开开发者模式或者右键检查进入,选择console (2)复制并运行代码 function ClickConnect(){ console. ...

  9. 带有关键词的行 txt文本处理

    原本的代码(只筛选出来自己要的)([python]文本处理:删除包含关键词的行.删除指定列.删除指定字符.替换关键字--_bandaoyu的博客-CSDN博客_python 删除csv还有特定词语的某 ...

  10. 关于之前ecplices没法正常导入使用fx包的笔记

    办法一:在java build path里的libraries里导入跟工作环境版本(或者ecplices的jdk版本)相配的jar包. 注:如果导入的包是要用fx的,可以不直接改整个程序的工作环境,可 ...