synchronized锁升级之偏向锁

article/2025/10/21 13:14:27

目录

一、什么是偏向锁?

二、偏向锁原理

三、偏向锁演示

四、偏向锁的处理流程

五、偏向锁的撤销

六、偏向锁的好处


一、什么是偏向锁?

HotSpot作者经过研究实践发现,在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低,引进了偏向锁。

偏向锁的“偏”,它的意思是锁会偏向于第一个获得它的线程,会在对象头(Mark Word中)存储锁偏向的线程ID,以后该线程进入和退出同步块时只需要检查是否为偏向锁、锁标志位以及ThreadID即可。

如下图是偏向锁对象头MarkWord布局:

二、偏向锁原理

偏向锁总是被第一个占用它的线程拥有,这个线程就是锁的偏向线程。在偏向锁的MarkWord中,就有一块区域用来记录偏向线程的ID,这个是在锁第一次被拥有的时候记录的。

因为记录了偏向线程ID,那么后续如果这个偏向线程进入和退出同步代码块的时候,就不需要再次加锁和解锁。

偏向锁再次进入同步代码块,是如何保证不需要再次加锁的?

偏向锁的线程会检查锁对象的MarkWord中是不是存放着自己的线程ID。

  • 相等

表示偏向锁现在就是偏向当前线程的,无需再尝试获得锁。以后每次同步,都会检查锁的偏向线程ID与当前线程ID是否一致,一致就直接进入同步,省去了CAS去更新对象头的操作,提高了锁的性能。

  • 不相等

表示偏向锁现在不是偏向当前线程的,此时发生了竞争,这时候当前线程就会尝试CAS去更新锁对象MarkWord中线程ID,尝试指定为自己的线程。此时也有两种情况:

1)、更新成功:表示已经将锁对象MarkWord中的线程ID替换为自己的线程ID,之前的线程可能刚好运行完,这时候锁重新偏向为当前线程,这种情况下,不会发生锁升级,锁仍然为偏向锁,只是偏向线程换成了另外一个线程;

2)、更新失败:表示之前的线程还在持有锁,那么当前线程只能一直CAS,当达到一定次数后,如果还没CAS成功,那么就会发生【偏向锁 -> 轻量级锁】的锁升级过程。

注意,偏向锁只有遇到其它线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程不会主动释放偏向锁的。

三、偏向锁演示

public class BiasedLockDemo01 {public static void main(String[] args) {Object objLock = new Object();new Thread(() -> {synchronized (objLock) {System.out.println(ClassLayout.parseInstance(objLock).toPrintable());}}, "t1").start();}
}

如上我们看到,markword的倒数三位是000,根据前面的图,000表示的是轻量级锁,此时只有一个线程访问,为什么输出来的不是偏向锁标识101呢?

原因其实是偏向锁在Java 6之后是默认启用的,但在应用程序启动几秒钟(默认延迟4秒)之后才会激活,可以使用 -XX:BiasedLockingStartupDelay=0参数关闭延迟,让其在程序启动时立刻启动。当然为了演示,也可以在程序中休眠5秒,等待偏向锁激活后。

下面我们添加运行时JVM参数,再次启动程序,观察内存布局:

可以看到关闭偏向锁延迟后,当前锁就是偏向锁了。

四、偏向锁的处理流程

当线程第一次访问同步块并获取锁时,偏向锁处理流程如下:

  • 1)、虚拟机将会把对象头中的是否偏向锁标志位设为“1”,即偏向模式;
  • 2)、使用CAS操作把获取到这个锁的线程的ID记录在对象的Mark Word之中 ,如果CAS操作成功,持有偏向锁的线程以后每次进入这个锁相关的同步块时,虚拟机都可以不再进行任何同步操作,效率极高;

五、偏向锁的撤销

前面提到,大部分情况下,锁都是被同一个线程获取到,持有偏向锁的线程不会主动释放锁。那么大部分情况下,不会涉及到偏向锁的撤销,当有另外的线程尝试竞争偏向锁的时候,这个时候才会涉及偏向锁的撤销流程。

举个例子,有线程A、线程B两个线程竞争获取锁,锁大部分情况下都被线程A持有,此时锁偏向于线程A,这样线程A每次进入/退出同步代码块,都无需再次加锁,只需判断MarkWord中保存的线程ID是否等于自己的线程ID。

线程A不会主动释放偏向锁,当运行了一段时间后,突然线程B过来尝试竞争这个偏向锁了,此时持有偏向锁的线程A会发生偏向锁的撤销。

偏向锁的撤销需要等待全局安全点(这个时间点没有代码正在执行),同时会检查持有偏向锁的线程A是否还在执行:

1)、线程A还是同步代码块中运行:发生【偏向锁 -> 轻量级锁】的升级过程。此时轻量级锁由原持有偏向锁的线程A持有,继续执行其同步代码,而正在竞争的线程B会在外面CAS自旋等待获取这个轻量级锁。

2)、线程A刚好执行完成同步代码块:则会将对象头MarkWord设置为无锁状态并撤销偏向锁,然后锁重新偏向到线程B,注意,这里会修改MarkWord中线程ID保存为线程B的线程ID。

流程图大体如下:

六、偏向锁的好处

偏向锁是在只有一个线程执行同步块时进一步提高性能,适用于一个线程反复获得同一个锁的情况。偏向锁可以提高带有同步但无竞争的程序性能。它并不一定总是对程序运行有利,如果程序中大多数的锁总是被多个不同的线程访问比如线程池,那偏向模式就是多余的,反而会影响效率。

注意,在JDK15中,已经废弃偏向锁。目前还是使用JDK1.8居多,所以我们还是有必要了解一下偏向锁。

 


http://chatgpt.dhexx.cn/article/awalcDiq.shtml

相关文章

Java无锁、偏向锁、轻量级锁、重量级锁,锁升级过程

2. 锁 2.1 无锁 Java对象刚创建时还没有任何线程来竞争,说明该对象处于无锁状态(无线程竞争它),这时偏向锁标识位是0,锁状态是01 。 2.2 偏向锁 偏向锁是指一段同步代码一直被同一个线程所访问,那么该…

偏向锁的获取和撤销详解

Java SE 1.6 为了减少获得锁和释放锁带来的性能消耗,引入了偏向锁和轻量级锁;在Java SE 1.6 中,锁共有4种状态,级别从底到高依次是:无锁状态、偏向锁状态、轻量级锁和重量级锁状态,这几种状态会随着竞争情况…

一篇文章说清 :无锁、偏向锁、轻量级锁、重量级锁

文章目录 前言一、无锁二、偏向锁三、轻量级锁(自选锁)四、重量级锁锁升级场景 前言 JDK1.6为了减少获得锁和释放锁所带来的性能消耗,引入了“偏向锁”和“轻量级锁”,所以在JDK1.6里锁一共有四种状态,无锁状态&#x…

synchronized的偏向锁、轻量级锁和重量级锁

文章目录 Java对象头偏向锁批量重偏向批量撤销 轻量级锁重量级锁Monitor 原理 Java对象头 普通对象 Mark Word在64 位虚拟机中的结构为 Mark Word后三(两)位表示 001:无锁状态101: 偏向锁00: 轻量级锁10&#xff1a…

Java synchronized偏向锁、轻量级锁、重量级锁

简介 synchronized锁共有偏向锁、轻量级锁、重量级锁三种类型,而这三种类型的加锁方式都是相同的,写代码时不用考虑加哪种锁。使用锁时对象首先会变为偏向锁状态,当有其它线程获取锁时会升级为轻量级锁(没有竞争锁)&am…

java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁

之前做过一个测试,详情见这篇文章《多线程 1操作的几种实现方式,及效率对比》,当时对这个测试结果很疑惑,反复执行过多次,发现结果是一样的: 1. 单线程下synchronized效率最高(当时感觉它的效率应该是最差…

偏向锁、轻量级锁、重量级锁的区别和解析

为了换取性能,JVM在内置锁上做了非常多的优化,膨胀式的锁分配策略就是其一。理解偏向锁、轻量级锁、重量级锁的要解决的基本问题,几种锁的分配和膨胀过程,有助于编写并优化基于锁的并发程序。 内置锁的分配和膨胀过程较为复杂&…

偏向锁是什么

偏向锁操作流程偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步 但是从我们跑的代码输出却看不到偏向锁这个东东。为啥对…

偏向锁的基本原理

偏向锁的基本原理 前面说过,大部分情况下,锁不仅仅不存在多线程竞争,而是总是由同一个线程多次获得,为了让线程获取锁的代价更低就引入了偏向锁的概念。怎么理解偏向锁呢?当一个线程访问加了同步锁的代码块时&#xff…

偏向锁,轻量级锁,重量级锁的核心原理

前言:大家好,我是小威,24届毕业生,在一家满意的公司实习。本篇文章是关于并发编程中偏向锁,轻量级锁,重量级锁的核心原理知识记录。 本篇文章记录的基础知识,适合在学Java的小白,也适…

深入探究synchronize锁机制

synchronized 有三种方式来加锁,分别是: **1. 修饰实例方法:**作用于当前实例加锁,进入同步代码前要获得当前实例的锁 **2. 静态方法:**作用于当前类加锁,进入同步代码前要获得当前类的锁 **3. 修饰代码块&…

偏向锁的原理与实战

文章目录 1. 偏向锁的核心原理2. 偏向锁代码演示3. 偏向锁的膨胀与撤销 1. 偏向锁的核心原理 如果不存在线程竞争的一个线程获得了锁,那么锁就进入偏向状态,此时Mark Word的结构变为偏向锁结构,锁对象的锁标志位(lock)…

Java并发 | 19.[锁机制] 偏向锁(CAS)

文章目录 1. 偏向锁分析回顾轻量级锁偏向锁的优势 2. 偏向锁(CAS)2.1. 偏向锁流程概述2.2. 锁升级 参考资料 1. 偏向锁分析 回顾轻量级锁 在上文 Java并发 | 18.[锁机制] 轻量级锁(CAS自旋锁)中对轻量级锁进行过解析&#xff0c…

Synchronized-偏向锁

偏向锁是什么? 是jdk1.6引入的一种锁优化方式。让 锁对象 偏心于第一次获取锁的线程,记住它的id,当下一次再有线程获取锁的时候,与记录的ID匹配,直接获取锁就行。是一种load-and-test的过程。 引入目的? …

面试题-- 什么是偏向锁

所谓的偏向,就是偏心,即锁会偏向于当前已经占有锁的线程 。 大部分情况是没有竞争的(某个同步块大多数情况都不会出现多线程同时竞争锁),所以可以通过偏向来提高性能。即在无竞争时,之前获得锁的线程再次获…

Java中的偏向锁,轻量级锁, 重量级锁解析

文章目录 参考文章Java 中的锁一些先修知识synchronized 关键字之锁的升级(偏向锁->轻量级锁->重量级锁)无锁 -> 偏向锁偏向锁的撤销(Revoke)偏向锁的批量再偏向(Bulk Rebias)机制偏向锁 -> 轻…

条件分布

1.离散型: 例1: 2.连续型:

关于多元正态分布的条件分布的证明

之前在机器学习 cs229学习笔记3 (EM alogrithm,Mixture of Gaussians revisited & Factor analysis )中直接给出了多元正态分布的条件概率 正好今天上课讲了多元正态分布的内容,但没有涉及条件概率,所以下来baidu了一下,找到一个不错的pp…

条件分布函数(离散-条件分布律)

一、离散随机变量的条件分布函数 1.0、条件分布函数定义 1.1、例 1.1.1、例1 1.1.2、例2 二、连续型随机变量的条件分布函数 2.1、连续随机变量的条件分布函数 2.2、条件概率密度函数