Java并发(十九)----Monitor原理及Synchronized原理

news2024/11/29 5:16:16

1、Java 对象头

以 32 位虚拟机为例

普通对象

|--------------------------------------------------------------|
|                     Object Header (64 bits)                  |
|------------------------------------|-------------------------|
|        Mark Word (32 bits)         |    klass Word (32 bits) |
|------------------------------------|-------------------------|

数组对象

|---------------------------------------------------------------------------------|
|                                 Object Header (96 bits)                         |
|--------------------------------|-----------------------|------------------------|
|        Mark Word(32bits)       |    Klass Word(32bits) |  array length(32bits)  |
|--------------------------------|-----------------------|------------------------|

其中 Mark Word 结构为

|-------------------------------------------------------|--------------------|
|                  Mark Word (32 bits)                  |       State        |
|-------------------------------------------------------|--------------------|
|  hashcode:25         | age:4 | biased_lock:0 | 01     |       Normal       |
|-------------------------------------------------------|--------------------|
|  thread:23 | epoch:2 | age:4 | biased_lock:1 | 01     |       Biased       |
|-------------------------------------------------------|--------------------|
|               ptr_to_lock_record:30          | 00     | Lightweight Locked |
|-------------------------------------------------------|--------------------|
|               ptr_to_heavyweight_monitor:30  | 10     | Heavyweight Locked |
|-------------------------------------------------------|--------------------|
|                                              | 11     |    Marked for GC   |
|-------------------------------------------------------|--------------------|

64 位虚拟机 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   |
|--------------------------------------------------------------------|--------------------|

参考资料

jvm - What is in Java object header? - Stack Overflow

2、Monitor 原理

Monitor 被翻译为监视器管程

每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的 Mark Word 中就被设置指向 Monitor 对象的指针

Monitor 结构如下

  • 刚开始 Monitor 中 Owner 为 null

  • 当 Thread-2 执行 synchronized(obj) 就会将 Monitor 的所有者 Owner 置为 Thread-2,Monitor中只能有一个 Owner

  • 在 Thread-2 上锁的过程中,如果 Thread-3,Thread-4,Thread-5 也来执行 synchronized(obj),就会进入 EntryList BLOCKED

  • Thread-2 执行完同步代码块的内容,然后唤醒 EntryList(阻塞队列) 中等待的线程来竞争锁,竞争是非公平的

  • 图中 WaitSet 中的 Thread-0,Thread-1 是之前获得过锁,但条件不满足进入 WAITING 状态的线程,后面讲 wait-notify 时会分析

注意:

  • synchronized 必须是进入同一个对象的 monitor 才有上述的效果

  • 不加 synchronized 的对象不会关联监视器,不遵从以上规则

3、synchronized 原理

static final Object lock = new Object();
static int counter = 0;
​
public static void main(String[] args) {
    synchronized (lock) {
        counter++;
    }
}

对应的字节码为

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: getstatic     #2                  // <- lock引用 (synchronized开始)
         3: dup                               // 复制一份引用
         4: astore_1                          // lock引用 -> slot 1
         5: monitorenter                      // 将 lock对象 MarkWord 置为 Monitor 指针
         6: getstatic     #3                  // <- i
         9: iconst_1                          // 准备常数 1
        10: iadd                              // +1
        11: putstatic     #3                  // -> i
        14: aload_1                           // <- lock引用
        15: monitorexit                       // 将 lock对象 MarkWord 重置, 唤醒 EntryList
        16: goto          24                  // 19-23 为异常处理
        19: astore_2                          // e -> slot 2 
        20: aload_1                           // <- lock引用
        21: monitorexit                       // 将 lock对象 MarkWord 重置, 唤醒 EntryList
        22: aload_2                           // <- slot 2 (e)
        23: athrow                            // throw e
        24: return
      Exception table:                      // 异常检测
         from    to  target type
             6    16    19   any            // 6-16 行出现异常 目标为19行
            19    22    19   any            // 19-22 行出现异常 目标为19行
      LineNumberTable:
        line 8: 0
        line 9: 6
        line 10: 14
        line 11: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  args   [Ljava/lang/String;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 19
          locals = [ class "[Ljava/lang/String;", class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4

注意

方法级别的 synchronized 不会在字节码指令中有所体现

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

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

相关文章

序列生成模型(一):序列概率模型

文章目录 前言1. 序列数据2. 序列数据的潜在规律3. 序列概率模型的两个基本问题 一、序列概率模型1. 理论基础序列的概率分解自回归生成模型 2. 序列生成 前言 深度学习在处理序列数据方面取得了巨大的成功&#xff0c;尤其是在自然语言处理领域。序列数据可以是文本、声音、视…

pytorch和pytorchvision安装

参考https://blog.csdn.net/2301_76863102/article/details/129369549 https://blog.csdn.net/weixin_43798572/article/details/123122477 查看我的版本 右键&#xff0c;nvivdia控制面板&#xff0c;帮助&#xff0c;系统信息 驱动程序版本号为528.49 更新很快的 CUDA版本…

stm32F4——BEEP与按键的实例使用

stm32F4——BEEP与按键的实例使用 蜂鸣器和按键的实质都是GPIO的使用&#xff0c;所以基本原理就不介绍啦&#xff0c;基本寄存器其实都是GPIO的高低电平的赋值&#xff0c;可以参考stm32——LEDGPIO的详细介绍 文章目录 stm32F4——BEEP与按键的实例使用一、BEEP二、 KEY三、通…

MySQL数据库 DML

目录 DML概述 添加数据 修改数据 删除数据 DML概述 DML英文全称是Data Manipulation Language(数据操作语言)&#xff0c;用来对数据库中表的数据记录进行增、删、改操作。 添加数据(工NSERT)修改数据(UPDATE)删除数据(DELETE) 添加数据 (1)给指定字段添加数据 INSERT …

Epic 安装失败,错误代码SUPQR1612,必要的先决条件安装失败,弹窗CD-ROM

错误记录 并且弹出来这个窗口the feature you are trying to use is on a CD-ROM or other removable disk that is not available. 让我寻找这个msi文件 正在想办法解决 如果有人能解决 麻烦告知评论区&#xff01;

网络安全事件分级指南

文章目录 一、特别重大网络安全事件符合下列情形之一的&#xff0c;为特别重大网络安全事件&#xff1a;通常情况下&#xff0c;满足下列条件之一的&#xff0c;可判别为特别重大网络安全事件&#xff1a; 二、重大网络安全事件符合下列情形之一且未达到特别重大网络安全事件的…

C++软件调试与异常排查技术从入门到精通学习路线分享

目录 1、概述 2、全面了解引发C软件异常的常见原因 3、熟练掌握排查C软件异常的常见手段与方法 3.1、IDE调试 3.2、添加打印日志 3.3、分块注释代码 3.4、数据断点 3.5、历史版本比对法 3.6、Windbg静态分析与动态调试 3.7、使用IDA查看汇编代码 3.8、使用常用工具分…

【Linux】cp问题,生产者消费者问题代码实现

文章目录 前言一、 BlockQueue.hpp&#xff08;阻塞队列&#xff09;二、main.cpp 前言 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯&#xff0c;而通过阻塞队列来进行通讯&#xff0c;所以生产者生产完数据之后不用…

将博客搬至微信公众号了

一、博客搬家通知 各位码友们好&#xff0c;大家是不是基本很少看 CSDN 了呢&#xff1f;平时开发是不都依靠着 chatGPT 来解决工作中的技术问题了&#xff0c;不过我觉得在工作中的使用场景各式各样的&#xff0c;具体问题还得自己具体去梳理逻辑&#xff0c;再考虑用什么样的…

【Vue第6-7章】vue-router与Vue UI组件库_Vue2

目录 第6章 vue-router 6.1 相关理解 6.1.1 vue-router的理解 6.1.2 对SPA应用的理解 6.1.3 路由的理解 6.2 基本路由 6.2.1 效果 6.2.2 总结&#xff1a;编写使用路由的3步 6.2.3 笔记与代码 6.2.3.1 笔记 6.2.3.2 30_src_路由的基本使用 6.3 嵌套&#xff08;多级…

股票价格预测 | Python实现基于ARIMA和LSTM的股票预测模型(含XGBoost特征重要性衡量)

文章目录 效果一览文章概述模型描述源码设计效果一览 文章概述 Python实现基于ARIMA和LSTM的股票预测模型(Stock-Prediction) Data ExtractionFormatting data for time seriesFeature engineering(Feature Importance using X

MX6ULL学习笔记(十二)Linux 自带的 LED 灯

前言 前面我们都是自己编写 LED 灯驱动&#xff0c;其实像 LED 灯这样非常基础的设备驱动&#xff0c;Linux 内 核已经集成了。Linux 内核的 LED 灯驱动采用 platform 框架&#xff0c;因此我们只需要按照要求在设备 树文件中添加相应的 LED 节点即可&#xff0c;本章我们就来学…

vue-cli创建一个vue3项目

通过命令创建VUE脚手架&#xff1a; npm install -g vue/cli 创建VUE项目&#xff1a; vue create npg***b 剩下的就是一路回车 npm install element-plus --save 入口文件main.ts import { createApp } from vue import App from ./App.vue import router from ./router…

【第3期】Springboot集成SpringSecurity+RSA+ECS免密登录

本期简介 RSA是非常安全的非对称加解密算法&#xff0c;单纯的RSA的原理和使用网络资料较多&#xff0c;本期不细讲RSA的原理&#xff0c;主要讲解实战&#xff0c;如何与SpringbootSpringSecurity集成起来&#xff0c;做到在安全框架基础上&#xff0c;对用户的密码进行加密存…

(2)Linux 操作系统||基本创建与操作

本章将浅谈一下 "操作系统是什么" 的问题&#xff0c;随后通过讲解一些 Linux 下的基本指令&#xff0c;显示目录内容、跳转操作和文件的创建与删除。在讲解的同时我会穿插一些知识点&#xff0c;比如 Linux 隐藏文件、路径等基础知识。 了解操作系统 什么是操作系统…

电子学会C/C++编程等级考试2021年09月(六级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:双端队列 定义一个双端队列,进队操作与普通队列一样,从队尾进入。出队操作既可以从队头,也可以从队尾。编程实现这个数据结构。 时间限制:1000 内存限制:65535输入 第一行输入一个整数t,代表测试数据的组数。 每组数据的…

桌面概率长按键盘无法连续输入问题

问题描述&#xff1a;概率性长按键盘无法连续输入文本 问题定位&#xff1a; 系统按键流程分析 图一 系统按键流程 按键是由X Server接收的&#xff0c;这一点只要明白了X Window的工作机制就不难理解了。X Server在接收到按键后&#xff0c;会转发到相应程序的窗口中。在窗…

海洋可视化大屏,Photoshop源文件

数据大屏通过实时的数据展示&#xff0c;可及时发现数据的变化和异常&#xff0c;以便及时采取措施。现分享海洋动力大数据监控、海洋数据监控系统、科技感海洋监控系统大屏模版的UI源文件&#xff0c;供UI设计师们快速获取PSD源文件完成工作 若需更多 大屏组件&#xff0c;请…

基于linux系统的Tomcat+Mysql+Jdk环境搭建(一)vmare centos7 设置静态ip和连接MobaXterm

特别注意&#xff0c;Windows10以上版本操作系统需要下载安装VMware Workstation Pro16及以上版本&#xff0c;安装方式此处略。 (可忽略 my*** 记录设置的vamare centos7 账号root/aaa 密码&#xff1a;Aa123456 ) 1、命令行和图形界面切换 如果使用的是VMware虚拟机&…

用Java实现根据数据库中的数量,生成年月份+序号递增

在日常开发中&#xff0c;经常会遇到根据年月日和第几号文件生成对应的编号&#xff0c;今天给大家提供一个简单的工具类 public static final Long CODE1L;/*** param select 数据库中数据总数* return*/public static String SubjectNo(Long select){// 在总数的基础上1&…