[Java-多线程] 锁原理(轻量级锁、锁膨胀、自旋锁、偏向锁)

news2024/9/22 15:37:54

1.Java对象头

我们平时使用的对象都是由两部分组成, 第一部分是对象头, 第二部分是对象的成员变量, 这里我么主要讲解对象头, 以32为虚拟机为例 :

Object Header (64 bits)

Mark Word (32 bits)

Klass Word (32 bits)

Klass Word : 每个对象都有类型 通过Klass Word就可以找到对应的类对象

Mark Word :

Mark Word (64 bits)

State

unused:25 | hashcode:31 | unused:1 | age:4 | biased_lock:0 | 01

Normal (普通的)

thread:54 | epoch:2 | unused:1 | age:4 | biased_lock:1 | 01

Biased

ptr_to_lock_record:62 | 00

Lightweight Locked (轻量级锁定)

ptr_to_heavyweight_monitor:62 | 10

Heavyweight Locked (重量级锁定)

| 11

Marked for GC

数字 01 代表的是加锁状态位


2.轻量级锁

使用场景: 如果一个对象虽然有很多线程正在访问, 但是多线程访问的时间都是错开的, 也就是没有竞争, 那么可以使用轻量级锁来优化

注 : 轻量级锁对于开发者来说是透明的, 仍然使用synchronized关键字

如下代码所示, 两个同步代码块的方法, 利用同一个对象锁

static final object obj new object();
public static void method1(){
synchronized(obj ){
    //同步块A 
    method2();
    }
}
public static void method2(){
synchronized(obj ){
    //同步块B
    }
}

2.1加锁

如果线程 Thread-0 直行到代码 synchronized(obj ), 就会在该方法的栈针中创建锁记录(Lock Record)对象, 这个锁记录对象其中包含两部分, 第一部分是对象指针, 另一部分存储我们要加锁对象的Mark Word 地址

  1. 让Object reference(指向的是对象的地址信息,方便通过ObjectMonitor来访问对应的锁对象) 指向右边的对象

  1. 将锁记录的数据和对象的Mark Word做交换, 表示给对象加锁, 这个带大家回顾一下对象头格式

在正常状态下Normal 最后两位显示的是01 但是如果是轻量级锁, 最后两位显示的是00, 最后交换的数据如下图所示

2.2解锁

当退出synchronized代码块(解锁时)锁记录的值不为null,这时使用cas将Mark Word的值恢复给对象头, 也就是将数据再次的交换


3.锁膨胀

场景 : 当其他线程Thread-1进行轻量级加锁时,Thread-0已经对该对象加了轻量级锁, Thread-1加锁失败进入膨胀锁流程, 改为重量级锁

这时Mark Word会指向 monitor 重量级锁的地址, 并且后两位会变成10

当Thread-0退出同步块解锁时,使用cas将Mark Word的值恢复给对象头,失败。这时会进入重量级解锁流程,即按照Monitor地址找到Monitor对象,设置Owner为null,唤醒EntryList中BLOCKED线程

了解Monitor如何解锁可以看这篇文章 : https://blog.csdn.net/qq_45481709/article/details/128651642?spm=1001.2014.3001.5501


4.自旋锁

重量级锁竞争的时候, 还可以使用自旋锁来优化, 如果当前线程自旋成功, 就避免了阻塞也就是减少了线程的上下文切换, 使得系统的性能开销减少

当线程2自旋重试的过程中, 线程1已经成功解锁, 在发现已经是无锁之后,线程2成功加锁就不会陷入阻塞状态

自旋锁失败情况

自旋会占用 CPU 时间,单核 CPU 自旋就是浪费,多核 CPU 自旋才能发挥优势。
在 Java 6 之后自旋锁是自适应的,比如对象刚刚的一次自旋操作成功过,那么认为这次自旋成功的可能性会
高,就多自旋几次;反之,就少自旋甚至不自旋,总之,比较智能。
Java 7 之后不能控制是否开启自旋功能

5.偏向锁

轻量级锁在没有竞争时(就自己这个线程),每次重入仍然需要执行 CAS 操作。

Java 6 中引入了偏向锁来做进一步优化:只有第一次使用 CAS 将线程 ID 设置到对象的 Mark Word 头,之后发现

这个线程 ID 是自己的就表示没有竞争,不用重新 CAS。以后只要不发生竞争,这个对象就归该线程所有

例如:

static final Object obj = new Object();
public static void m1() {
synchronized( obj ) {
// 同步块 A
m2();
 }
}
public static void m2() {
synchronized( obj ) {
// 同步块 B
m3();
 }
}
public static void m3() {
synchronized( obj ) {
// 同步块 C
 }
}

在改为偏向锁之后, 就会将将线程 ID 设置到对象的 Mark Word 头

扫描下方公众号二维码 回复: 多线程 领取多线程面试题 👇 👇 👇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182060.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

离散数学与组合数学-07命题逻辑

文章目录离散数学与组合数学-07命题逻辑7.1 命题逻辑-什么是命题7.1.1 数理逻辑发展7.1.2 什么是命题7.1.3 复合命题7.2 命题逻辑-命题联结词7.2.1 否定联结词7.2.2 合取联结词7.2.3 析取联结词7.2.4 蕴涵联结词7.2.5 等价联结词7.3 命题逻辑-命题符号化及应用7.3.1 联结词总结…

什么是JMM模型

什么是JMM模型?Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素&#xff…

11. 线程本地变量ThreadLocal的使用

1. 对ThreadLocal的理解 ThreadLocal,有人称它为线程本地变量,也有人称它为线程本地存储,其实表达的意思是一样的。ThreadLocal在每一个变量中都会创建一个副本,每个线程都可以访问自己内部的副本变量。 在多线程环境下&#xff…

tomcat 的并发能力分析

tomcat 参考:Tomcat的3个参数acceptCount、maxConnections、maxThreads Tomcat 的核心组件 Tomcat 由 2 大核心组件组成:Connector、Container Tomcat 处理请求的过程 请求在 tomcat 服务器的处理过程(BIO 模式) 客户端与服务…

嵌入式串行通信协议

嵌入式系统中,不同芯片之间通常使用串行总线的方式进行连接,根据器件行业规范、应用场景,不同芯片通常选择不同的串行通信接口进行通信。常用的串行通信接口有:1-Wire、I2C、SPI、UART。 一、1-Wire 1-wire单总线是Maxim的全资子…

bodgeito通关教程

6.bodgeito通关教程 进入网站整体浏览网页 点击页面评分进入关卡 一般搭建之后这里都是红色的&#xff0c;黄色是代表接近&#xff0c;绿色代表过关 首先来到搜索处本着见框就插的原则 构造payload输入 <script> alert(/xss/)</script>成功弹窗xss&#xff0c;发…

Redis数据库

1.Redis简介 1.1Redis简介 Redis 是当前互联网世界最为流行的 NoSQL&#xff08;Not Only SQL&#xff09;数据库。NoSQL 在互联网系统中的作用很大&#xff0c;因为它可以在很大程度上提高互联网系统的性能。 Redis 具备一定持久层的功能&#xff0c;也可以作为一种缓存工具…

c++实现堆排序

看了一下优先队列&#xff0c;查了一下堆排序。堆排序主要就是建最大堆&#xff08;最小堆&#xff09;和交换2个操作。如果建的是最大堆&#xff0c;那么交换的时候&#xff0c;父节点就和最大的子节点比较&#xff0c;如果它比最大的子节点还大&#xff0c;那就不用比了。因为…

STM32MP157开发板Linux+Qt项目实战:智能猫眼

stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器&#xff0c;集成2Cortex-A7核和1个Cortex-M4 核&#xff0c;A7核上可以跑Linux操作系统&#xff0c;M4核上可以跑FreeRTOS…

docker 搭建postgres 主从 pgadmin

准备工作 创建一个docker bridge 网路用于测试 docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 pgnetwork # 查看 docker network ls 设置了网段为 192.168.0.0&#xff0c;规划主从库IP端口如下&#xff1a; 主库 192.168.0.101:5432 从库…

Ubuntu16.04安装深度学习环境(CUDA9.2+PyTorch0.4.1+Python2.7)

之前已经安装好了显卡驱动&#xff0c;接着就可以安装CUDA了于是又找了好几篇文章进行参考&#xff1a;https://zhuanlan.zhihu.com/p/361190040https://blog.csdn.net/qq_43665602/article/details/125752433https://blog.csdn.net/myg22/article/details/84029924https://blo…

二、数据缓存

文章目录数据缓存1.标准缓存流程2.缓存更新一致性3.缓存穿透解决方案缓存空对象布隆过滤器4.缓存雪崩解决方案5.缓存击穿解决方案互斥锁逻辑过期6.使用函数式接口封装工具类学习 黑马点评项目整理总结: https://www.bilibili.com/video/BV1cr4y1671t/?vd_source5f3396d3af2c39…

webpack项目配置

30.webpack——webpack5新特性&#xff08;启动、持久化缓存、资源模块、URIs、moduleIds和chunkIds、tree shaking、nodeJs的polyfill被移除、模块联邦&#xff09;_俞华的博客-CSDN博客_chunkids webpack和vite的区别 - 简书 vite介绍 &#xff5c; 与其他构建工具做比较&…

【ONE·C || 字符串和内存函数】

总言 C语言&#xff1a;字符串和内存函数使用介绍。 文章目录总言1、求字符串长度&#xff1a;strlen1.1、基本介绍1.2、演示说明1.2.1、strlen输出1.2.2、strlen返回值1.3、模拟实现strlen1.3.1、计数器写法1.3.2、递归写法1.3.3、指针-指针写法2、长度不受限制的字符串函数2.…

educoder数据结构 图 无错AC代码版

目录 第1关&#xff1a;实现图的宽度优先遍历 任务描述 相关知识 编程要求 测试说明 输入输出格式说明&#xff1a; 样例输出 Ac_Code 第2关&#xff1a;实现图的深度优先遍历 任务描述 相关知识 测试说明 输入输出格式&#xff1a; 样例输出 AC_Code 第1关&am…

2023年flag

开头总是让人那么茫然无措&#xff0c;在这里记录梳理上一年。以期找到前进的方向&#xff0c;迈开新一年的第一步&#xff0c;然后不断前行。 回顾上一年 首先想到的第一件事&#xff0c;11月换了个工作依然是Java开发10月份准备了软件工程中级考试并考过读了几本技术的书籍…

【设计模式】我终于读懂了享元模式。。。

祝大家开工大吉&#x1f9e7;&#x1f9e7;&#x1f9e7;&#xff01;&#xff01;主页有红包哦 点这里 文章目录祝大家开工大吉&#x1f9e7;&#x1f9e7;&#x1f9e7;&#xff01;&#xff01;主页有红包哦 [点这里](https://blink.csdn.net/details/1469531)&#x1f9e7;…

Python基础学习 -- 进程锁

一、join函数的作用1、等子进程执行完&#xff0c;主进程再结束2、将子进程都存储到一个列表&#xff0c;每个子进程都调用一下join方法if __name__"__main__":print("我是主线程")stime.time()a[2,3,4]b[] #存储创建好的进程for i in a:pProcess(targetfu…

入门算法,这篇文章你得看!(java、算法基础、常用算法)

想用Java快速入门算法&#xff1f;这篇文章你得看&#xff01; 提示&#xff1a;本文章适合想要入门算法&#xff0c;并且想 “快速” 达到一定成果的同学们阅读~ 文章非常非常非常长&#xff08;可能是你见过最长的博客&#xff09;&#xff01;&#xff01;&#xff01; 阅读…

Authing 身份云入选《数字身份治理与管理(IGA)应用实践指南》报告

身份是物理实体映射在网络空间的一串数字代码&#xff0c;是数字世界的通行证。掌控了统一的权威数字身份就等同掌控了实体在数字空间的行为。网络业务的快速发展&#xff0c;使业务与安全深度融合到一起&#xff0c;并使数字身份成为数字化经济建设的重要基石。同一实体可以更…