聊一聊java中synchronized的实现原理

51单片机基础知识 前言 周末闲着无聊,以后定时更新一期关于51单片机的学习案例,以供大家平时参考使用。至于单片机,你可以理解为人的大脑,而人各项身体器官的运作需要意识给到大脑,然后大脑再驱动我们的中枢神经进行相应的动作,这里的意识可以理解为我们要写的程序,而人的器官相当于各种输出设备,例如我们以后要学的LED、电机、各种传感器等等。学好单片机能让你找到一份相对不错的工作,当然越可观的东西也是要付出相应努力的。 一、51单片机是什么? 通常我们一说到 51 单片机,指的都是兼容IntelMCS-51体系架构的一系列单片机,而 阅读详情

是什么:

synchronized  是 Java 中用于控制多个线程对共享资源的访问的关键字,以确保在并发环境中数据的完整性和一致性。

synchronized 关键字可以作用于方法或代码块中。

代码示例:

public class SynchronizedTest {

    private int count = 0;

    /**
     * synchronized用在方法上
     */
    public synchronized void increase() {
        count++;
    }

    /**
     * synchronized用在代码块上
     */
    public void increase2() {
        synchronized (this) {
            count++;
        }
    }
}

实现原理:

synchronized 的实现原理主要基于 Java 的内存模型以及对象锁机制。

Java 内存模型

Java 内存模型(JMM)定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程使用到的主内存副本的拷贝,线程对变量的所有操作(读取、赋值等)都必须在自己的本地内存中进行,而不能直接读写主内存中的变量。

锁机制

synchronized 关键字在 Java 中的常用使用方式:

  • 修饰实例方法:作用于当前实例加锁,进入同步代码前要获得当前实例的锁。
  • 修饰静态方法:作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁。
  • 修改代码块:指定加锁对象,进入同步代码块前要获得指定对象的锁。

当线程进入 synchronized 修饰的方法或代码块时,它会尝试获取对象的锁。如果锁已被其他线程持有,则当前线程会阻塞,直到持有锁的线程释放锁。一旦线程获取到锁,它就可以安全地执行同步代码块中的操作,而不会被其他线程打断。

实现细节:

当深入探讨 synchronized 的实现细节时,我们需要考虑 JVM、字节码指令、锁的状态以及锁升级等多个方面。

1. JVM 层面的支持

JVM 通过内部对象监视器(也称为 Monitor 或内置锁,下一节介绍)来实现 synchronized。每个对象都有一个与之关联的监视器锁,当线程进入 synchronized 代码块或方法时,JVM 会尝试获取该对象的监视器锁。

2. 字节码指令

当编译器遇到 synchronized 关键字时,它会生成特定的字节码指令来处理同步逻辑。例如,对于实例方法的同步,编译器会插入 monitorenter 和 monitorexit 指令。当线程执行到 monitorenter 指令时,它会尝试获取对象的锁;当执行到 monitorexit 指令时,它会释放对象的锁。

3. 锁的状态与偏向锁

为了优化性能,JVM 中的锁有多种状态,包括无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。synchronized 的实现会根据锁的状态和竞争情况来进行相应的优化。

  • 偏向锁:这是 JVM 的一种锁优化手段。当一个线程首次访问同步代码块并获取锁时,JVM 会将锁对象头中的标记位设为“偏向模式”,记录持有锁的线程 ID,以后该线程进入和退出同步块时不需要进行 CAS 操作来加锁和解锁,只需检查是否为偏向锁以及锁是否指向当前线程的 ID。偏向锁可以提高无竞争情况下的性能。

4. 锁升级

当锁竞争加剧时,JVM 会进行锁升级来确保线程安全。

  • 轻量级锁:当多个线程交替访问同步块时,JVM 会尝试使用轻量级锁来避免线程阻塞。轻量级锁通过 CAS(Compare-and-Swap)操作来尝试获取锁,如果成功则继续执行,如果失败则进入自旋等待状态,尝试重新获取锁。轻量级锁可以减少线程阻塞的开销,但在竞争激烈的情况下可能会导致 CPU 自旋消耗过多资源。
  • 重量级锁:当轻量级锁无法满足需求时,JVM 会将锁升级为重量级锁。重量级锁采用传统的互斥量(Mutex)机制来实现,线程在获取锁时会进入阻塞状态,等待其他线程释放锁。重量级锁可以确保线程安全,但可能导致线程频繁阻塞和唤醒,降低性能。

5. 锁的释放与可重入性

当一个线程持有某个对象的锁时,它可以多次进入由同一把锁保护的同步块,这就是锁的可重入性。JVM 通过维护一个计数器来记录线程对锁的重入次数,每次线程进入同步块时计数器加一,退出时减一,当计数器为零时释放锁。

6. 公平性与非公平性

synchronized 默认的锁是非公平的,即等待获取锁的线程不一定按照它们请求锁的顺序来获取锁,这可能导致饥饿现象(某些线程长时间得不到执行)。虽然 JVM 也支持公平锁,但 synchronized 关键字本身并不直接提供公平锁的实现。如果需要公平锁,可以使用 java.util.concurrent.locks 包中的 ReentrantLock 类,并设置其公平性参数为 true。

JVM 内部对象监视器Monitor

JVM中的内部对象监视器(也称为Monitor或内置锁)是Java并发编程中的一个核心概念,它提供了一种机制来确保同一时间只有一个线程可以执行某个代码段,从而实现对共享资源的同步访问。

监视器可以理解为一个特殊的房间,这个房间同一时刻只能有一个线程进入。这个房间中包含了一些数据和代码,这些数据和代码在任意时刻只能被一个线程访问。当一个线程想要进入这个特殊房间时,它首先需要在“走廊”(Entry Set)中排队等待。调度器将基于某种标准(如FIFO)来选择排队的线程进入房间。如果因为某些原因,线程暂时无法继续执行(例如,线程被挂起),它将被送到另一个专门用于等待的房间(Wait Set),并可以在稍后再次尝试进入特殊房间。

操作系统的管程(monitor)是概念原理,ObjectMonitor是它的原理实现。

在Java虚拟机(HotSpot)中,Monitor(管程)是由ObjectMonitor实现的,其主要数据结构如下:

ObjectMonitor() {
    _header       = NULL;
    _count        = 0; // 记录个数
    _waiters      = 0,
    _recursions   = 0;
    _object       = NULL;
    _owner        = NULL;
    _WaitSet      = NULL;  // 处于wait状态的线程,会被加入到_WaitSet
    _WaitSetLock  = 0 ;
    _Responsible  = NULL ;
    _succ         = NULL ;
    _cxq          = NULL ;
    FreeNext      = NULL ;
    _EntryList    = NULL ;  // 处于等待锁block状态的线程,会被加入到该列表
    _SpinFreq     = 0 ;
    _SpinClock    = 0 ;
    OwnerIsThread = 0 ;
  }

Java Monitor的工作机理:

  • 想要获取monitor的线程,首先会进入_EntryList队列;
  • 当某个线程获取到对象的monitor后,进入Owner区域,设置为当前线程,同时计数器count加1;
  • 如果线程调用了wait()方法,则会进入WaitSet队列。它会释放monitor锁,即将owner赋值为null,count自减1,进入WaitSet队列阻塞等待。
  • 如果其他线程调用 notify() / notifyAll() ,会唤醒WaitSet中的某个线程,该线程再次尝试获取monitor锁,成功即进入Owner区域。
  • 同步方法执行完毕了,线程退出临界区,会将monitor的owner设为null,并释放监视锁。

在Java中,每个对象都有一个与之关联的监视器。当线程进入synchronized代码块或方法时,它会自动获取该对象的监视器锁,并在退出synchronized代码块或方法时释放该锁。如果其他线程试图获取已经被锁定的对象的监视器锁,它将被阻塞,直到当前线程释放锁为止。

Java对象头中的MarkWord部分存储了与锁相关的信息,如锁状态标志、线程持有的锁等。这使得JVM能够跟踪和管理对象的锁定状态。

总的来说,JVM中的内部对象监视器是一种强大的同步工具,它有助于程序员编写出线程安全的代码,从而避免数据竞争和不一致等问题。然而,过度使用或不当使用监视器也可能导致性能下降或死锁等问题,因此在使用时需要谨慎。

实际案例分析:

我们再回过头来看看最开始的示例代码SynchronizedTest类反编译之后的代码,如下:

执行命令:

javap -verbose SynchronizedTest

输出:(太长,所以截了多张图)

执行命令:

javap -c SynchronizedTest

输出:

从以上反编译的信息中,我们可以看到:

synchronized直接作用于方法increase时的flags:ACC_SYNCHRONIZED,当线程执行有ACCSYNCHRONI标志的方法,需要获得monitor锁。每个对象都与一个monitor相关联,线程可以占有或者释放monitor;

synchronized作用于increase2方法中的代码块时的code:monitorenter,monitorexit,当线程执行到monitorenter的时候要先获得monitor锁,才能执行后面的方法。当线程执行到monitorexit的时候则要释放锁。

部分参考内容:两万字!多线程硬核50问!

IGS精密星历高效获取与解析指南 本文详细介绍了IGS精密星历在高精度定位中的核心作用,对比了IGS Final、IGR和IGU等不同产品的精度与时效性差异。指南提供了从武汉大学、NASA CDDIS等数据中心高效下载数据的实战方法,并深入解析了SP3文件格式,帮助用户掌握精密星历的获取、解析与自动化处理技巧,以支持厘米级定位应用。 阅读详情

相关推荐

【机器学习】实验3,贝叶斯垃圾邮件识别(完整代码实现+报告)

电子邮件是互联网的一项重要服务,在大家的学习、工作和生活中会广泛使用。但是大家的邮箱常常被各种各样的垃圾邮件填充了。有统计显示,每天互联网上产生的垃圾邮件有几百亿近千亿的量级。因此,对电子邮件服务提供商来说,垃圾邮件过滤是一项重要功能。而朴素贝叶斯算法在垃圾邮件识别任务上一直表现非常好,至今仍然有很多系统在使用朴素贝叶斯算法作为基本的垃圾邮件识别算法。本次实验数据集来自的中文垃圾邮件数据集,目录解压后包含三个文件夹,其中data目录下是所有的邮件(未分词),已分词好的邮件在data_cut目录下。

高丽大学人工智能硕士在读|专注大模型、RAG、OCR与AI工程实践 5026

synchronized原理

由于 Java 面向对象的思想,在 JVM 中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能,这些标记字段组成了对象头。

小鲁蛋的博客 860

黏菌算法(Slime Mould Algorithm,SMA)

这是一篇关于黏菌算法的总结博客,包含算法思想,算法步骤,求函数最值(Python实现),算法改进等,持续更新ing

weixin_46838605的博客 1万+

Java并发——Synchronized实现原理详解

Synchronized实现原理详解一、Synchronized使用场景二、Synchronized实现原理三、锁的优化1、锁升级2、锁粗化3、锁消除 一、Synchronized使用场景 Synchronized是一个同步关键字,在某些多线程场景下,如果不进行同步会导致数据不安全,而Synchronized关键字就是用于代码同步。什么情况下会数据不安全呢,要满足两个条件:一是数据共享(临界资源),二是多线程同时访问并改变该数据。 Synchronized锁的3种使用形式(使用场景): Synchron

蒋蒋 1219

直流有刷电机H桥控制实战:从原理图到PWM调速(附DR70x驱动芯片详解)

本文详细解析了直流有刷电机H桥控制的核心技术,从原理图设计到PWM调速实现,特别针对DR70x驱动芯片的应用进行了深入探讨。文章涵盖了H桥电路的电流路径分析、PWM调速的工程细节、DR70x驱动芯片的工作原理及典型应用电路设计,并提供了实测波形分析和故障排查方法,为工程师提供了一套完整的解决方案。

weixin_29215815的博客 149

Bellhop水声信道模型的仿真

Bellhop是一种基于射线追踪的水声信道模型,广泛用于预测水下环境中的声压场。它通过模拟声波在水中的传播路径,计算声场分布,适用于复杂的水下通信场景。

yt94832的博客 1315

深入解析 Java 中的 Synchronized:原理、实现与性能优化

synchronized 同步块是 Java 提供的一种原子性内置锁,Java 中的每个对象都可以把它当作一个同步锁来使用,这些 Java 内置的使用者看不到的锁被称为内部锁,也叫作监视器锁。线程的执行:代码在进入 synchronized 代码块前会自动获取内部锁,这时候其他线程访问该同步代码块时会被阻塞挂起。拿到内部锁的线程会在正常退出同步代码块或者抛出异常后或者在同步块内调用了该内置锁资源的 wait 系列方法时释放该内置锁。

微笑听雨 9288

CCF CSP历年题解(python)

菜鸡一枚,没参加过算法竞赛,单纯为了抵研究生考试复试才刷题,通过写博客记录下来,希望能和大家互相交流,代码质量不高,大家见谅。 因为考研等原因,题目不定期更新… 第一题 201312-1出现最多次数的数 ...

weixin_44690402的博客 5004

一文彻底搞懂synchronized实现原理

synchronized 是 Java 中实现线程同步的关键字,用于保护共享资源的访问,确保在多线程环境中同一时间只有一个线程能够访问特定的代码段或方法。它提供了互斥性、可见性和有序性三个基本特性,确保了线程间操作的原子性和数据的一致性。

永远在路上 7511

使用Python与OpenCV实现基于霍夫变换的圆形缺陷检测与定位详细教程

本文详细探讨了如何使用Python和OpenCV库,通过图像边缘检测和霍夫变换实现圆形对象的检测与缺陷定位。我们不仅介绍了算法的基本原理,还通过具体的代码示例展示了如何在实际应用中实现这些技术。对于工业检测和医学影像分析,本文的方法提供了高效且易于实现的解决方案。随着图像处理技术的不断发展,未来我们可以期待更多新算法和新技术的应用,如深度学习与传统方法的结合,以及多传感器融合技术的引入,这将进一步提升缺陷检测与定位的效率和准确性。

qq_38334677的博客 1296

多跳问答技术解析:从原理到金融领域实践

多跳问答(Multi-hop QA)是自然语言处理中的高级任务,要求系统通过多步推理整合分散信息来回答问题。其核心技术在于理解文档间的复杂关联,相比单跳问答需要更精细的数据集设计和模型架构。在金融、医疗等专业领域,多跳问答能有效处理如'腾讯大股东投资的港股上市公司'这类需要串联多个信息点的问题。典型实现方案包括MR-Search框架的三级检索器设计,分别处理实体召回、关系匹配和数值比较。当前最佳实践表明,结合稠密检索与稀疏检索的混合策略,配合动态路由机制,能在保持较高精度的同时控制计算成本。这类技术在金融风

weixin_42566072的博客 606

Java并发之synchronized实现原理

1. synchronized三种使用方式 线程安全是并发编程的重点,如果我们出现安全问题将会导致严重的生产问题(比如秒杀时多卖了一台手机)。并发编程中造成线程安全的诱因主要有两点:一是存在共享资源(也称为临界资源)。二是 二级 三级目录 ......

qq_39093474的博客 976

【银河麒麟V10】【桌面】【服务器】系统启动问题

1、如果之前运行好好的,重启后系统报错,一般80%是因为fstab的问题,回想下之前有没有添加过外接存储,修改过/etc/fstab,如果是的话一般是因为存储异常(比如网络存储无法连接,本地存储路径变化)导致系统开机自检失败,导致无法正常启动; 处理方式:进入单用户(单用户进入的几种方式上面有专门文章介绍),修改/etc/fstab,将新增的内容暂时注释掉,然后重启系统,能正常进入系统后再分析失败原因。 ...

桂安俊@KylinOS 3万+

Synchronized实现原理

查看带有Synchronized语句块的class文件可以看到在同步代码块的起始位置插入了moniterenter指令,在同步代码块结束的位置插入了monitorexit指令。(JVM需要保证每一个monitorenter都有一个monitorexit与之相对应,但每个monitorexit不一定都有一个monitorenter)但是查看同步方法的class文件时,同步方法并没有通过指令moni...

Lzc的博客 1万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

synchronized底层实现原理及锁优化

一、概述 1、synchronized作用 原子性:synchronized保证语句块内操作是原子的 可见性:synchronized保证可见性(通过“在执行unlock之前,必须先把此变量同步回主内存”实现) 有序性:synchronized保证有序性(通过“一个变量在同一时刻只允许一条线程对其进行lock操作”) 2、synchronized的使用 修饰实例方法,对当前实例对象加锁 修饰...

Medlen 7万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Synchronized底层核心原理

本篇文章是关于并发编程中Synchronized锁的底层核心原理知识记录,由于篇幅原因,下篇文章将介绍各种锁的优化原理。

小威的博客 8695

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

synchronized 底层实现原理?

synchronized 底层实现原理? 一、作用 确保线程互斥的访问同步代码 保证共享变量的修改能够及时可见 有效解决重排序问题 二、用法 修饰普通方法 修饰静态方法 修饰代码块 三、原理 同步代码块是通过 monitorenter 和monitorexit 指令获取线程的执行权 同步方法通过加ACC_SYNCHRONIZED 标识实现线程的执行权的控制 测...

ConstXiong 1万+

synchronized实现原理

synchronized的处理多次提到了监视器锁这个概念。什么是监视器锁呢?监视器锁是synchronized实现的核心,也是JVM保证多线程机制的核心。监视器锁严格来讲,要分成,锁和监视器来讲。我们先对这两个概念进行初步的了解,之后再串联动态执行时的机制。所谓的“锁”究竟是什么对象头数据解析在java中,每一个对象在存储时,具备一个对象头。他是对象在内存布局中的一部分。主要是用于存储对象的一些元数据信息,比如哈希码,分代年龄,锁状态等。对象头的信息对于JVM实现锁机制,垃圾回收机制,具有重大的意义。

童年纸飞机的博客 1094

【java基础】synchronized实现原理

synchronized关键字可以修饰方法或者代码块,它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者代码块中,它保证了线程对变量访问的可见性和排他性 Java中的每一个对象都可以作为锁,具体表现为以下3种形式 1、对于同步代码块,锁是synchronized括号里配置的对象 2、对于普通同步方法,锁是当前实例对象 3、对于静态同步方法,锁是当前类的Class对象 通过具体的代码来说明加锁对象的不同情况 public class Main { public...

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 1373

synchronized的底层实现原理

synchronized的底层实现原理 转载自https://baijiahao.baidu.com/s?id=1612142459503895416&wfr=spider&for=pc,记录下别人分析的结果。 synchronized锁的底层实现 MDove:我们都知道,对象被创建在堆中。并且对象在内存中的存储布局方式可以分为3块区域:对象头、实例数据、对齐填充。其中对象头,便是我们今天的主角。 关于实例数据、对齐填充的作用,各位小伙伴可以参考《深入理解Java虚拟机》。 MDove:对

chao18867105705的博客 1892

【原理】【Java并发】【synchronized】适合中学者体质的synchronized原理

【Java并发】【synchronized】适合初学者体质入门的synchronized一定很想了解synchronized更多更多吧!没问题,主播来咯!3、2、1,上文章📖Monitor(监视器)并不是直接存储在对象头()中,但对象头中的信息会指向 Monitor。具体来说,当对象被用作锁时,JVM 会根据锁状态(无锁、偏向锁、轻量级锁、重量级锁)在对象头中存储不同的信息。只有在重量级锁状态下,对象头中的指针才会指向一个独立的 Monitor 对象(位于堆内存中)。// 核心字段。

flzjkl的博客 1636

Java synchronized的实现原理?

Java synchronized的实现原理?

java1234的博客 1200

java sync 实现原理_Synchronized 天天用,实现原理你懂吗?

来源:小小木的博客www.cnblogs.com/wyc1994666/p/11748212.htmlSynchronized 关键字算是Java的元老级锁了,一开始它撑起了Java的同步任务,其用法简单粗暴容易上手。但是有些与它相关的知识点还是需要我们开发者去深入掌握的。比如,我们都知道通过 Synchronized 锁来实现互斥功能,可以用在方法或者代码块上,那么不同用法都是怎么实现的,以及都...

weixin_32098191的博客 1653

Synchronized 底层原理

我们先通过反编译下面的代码来看看Synchronized是如何实现对代码块进行同步的: package com.paddx.test.concurrent; public class SynchronizedDemo { public void method() { synchronized (this) { System.out.printl...

3516

深入分析 synchronized 的实现原理

深入分析 synchronized 的实现原理 记得刚刚开始学习 Java 的时候,一遇到多线程情况就是 synchronized ,相对于当时的我们来说 synchronized 是这么的神奇而又强大,那个时候我们赋予它一个名字“同步”,也成为了我们解决多线程情况的百试不爽的良药。 但是,随着我们学习的进行我们知道 synchronized 是一个重量级锁,相对于 Lock ,它会显得那么笨重,...

木村的博客 2876

java synchronized的实现原理

面试经常被问道synchronized关键字,有的是以题目的形式让你判断能不能执行,有的直接问实现原理,今天梳理一下 使用方式 Java中每一个对象都可以作为锁,这是synchronized实现同步的基础: 普通同步方法,锁是当前实例对象 静态同步方法,锁是当前类的class对象 同步方法块,锁是括号里面的对象 当一个线程访问同步代码块时,它首先是需要得到锁才能执行同步代码,当退出或者抛出异...

zzx410527的专栏 256
上一篇: 聊一聊java中的volatile关键字是如何保障变量的可见性的
下一篇: 聊聊java中的CountDownLatch,CyclicBarrier,Semaphore
Jack_abu
博客等级 码龄10年 633粉丝 78原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jack_abu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值