news 2026/5/6 17:08:27

并发编程--synchronized

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
并发编程--synchronized

3. 第三个概念集合——对synchronized锁,原理,概念,API调用的集合,以及锁升级,在使用API的时候,发生了什么事情

synchronized的使用背景和基础概念

这个在JavaSE的时候就有介绍。
就是因为线程多线程,在Java中的时候,数据不安全。
线程访问数据,到线程的内存里
不是CPU的级别的内存
会导致超卖的问题。

这个时候,官方已经解决这个问题,就是创造了这个synchronized关键字。

这个时候使用synchronized这个锁,就可以保证,
同一时间,只会有一个线程访问内存里的数据。

我们基础层面的掌握,就是掌握一下,什么时候使用这个关键字,怎么使用这个关键字。

补充说明:
这里的“线程的内存”指的是Java内存模型(JMM)中定义的工作内存(线程私有栈内存中的变量副本),而不是CPU缓存。每个线程从主内存拷贝共享变量到自己的工作内存中操作,操作完成后再写回主内存,这个过程如果不加控制就会导致可见性问题。
“超卖问题”典型场景如:两个线程同时读取到库存=1,各自在工作内存中减到0,再先后写回主内存,最终结果还是0,但实际卖出了两份。synchronized通过互斥访问解决了这种并发修改的不安全问题。


synchronized在代码使用层面需要了解的概念和知识

synchronized这个关键字,可以修饰什么,怎么使用

补充说明——synchronized的三种使用方式:

  1. 修饰实例方法

    publicsynchronizedvoidmethod(){// 同步代码}

    锁对象:当前实例对象(this)

  2. 修饰静态方法

    publicstaticsynchronizedvoidstaticMethod(){// 同步代码}

    锁对象:当前类的Class对象(如 MyClass.class)

  3. 修饰代码块

    synchronized(lockObject){// 同步代码}

    锁对象:括号中指定的任意对象

使用选择建议:

  • 方法内只有少量代码需要同步 → 用同步代码块,减少锁持有时间,提高并发度
  • 整个方法都需要同步 → 可以修饰方法,代码更简洁
  • 控制粒度精细(如一个方法内对不同资源分别加锁) → 用不同的锁对象分开控制

synchronized在代码原理层面需要了解的概念和知识

我们看一下synchronized的例子。

// 同步代码块的常见用法privatefinalObjectlock=newObject();// 专门的锁对象publicvoidsomeMethod(){synchronized(lock){// 需要同步的代码}}

这个要锁一个对象,为什么是锁一个对象?

我们知道,对象在JVM里,可以分为:

  • 对象头(Header)
  • 实例数据(Instance Data)
  • 填充数据(Padding)

对象头里面有丰富的信息,包括:

  • Mark Word(标记字段)
  • Klass Pointer(类型指针)
  • 数组长度(如果对象是数组)

Mark Word 中存储了与锁相关的核心信息:

  • 哈希码(hashCode)
  • GC分代年龄(age)
  • 锁状态标志位(01、00、10、11)
  • 指向线程ID的指针(偏向锁模式下)
  • 指向重量级锁(monitor)的指针

补充说明:为什么锁的是一个对象?

在JVM设计中,每个Java对象都可以天然地作为锁,根本原因就在于对象头的Mark Word中包含了锁状态信息。当线程想要进入同步块时,JVM会检查目标对象的对象头:

  1. 判断当前锁状态(无锁、偏向锁、轻量级锁、重量级锁)
  2. 根据状态决定采用哪种锁机制
  3. 通过CAS或monitor机制竞争锁
  4. 成功则修改对象头的锁状态记录,失败则阻塞或自旋等待

锁对象的选择原则:

  • 多个线程竞争的必须是同一个对象(同一内存地址的同一个实例)
  • 如果是不同对象,就是不同的锁,不会互斥
  • 常用做法:使用private final Object lock = new Object()可以防止锁对象被意外修改

锁升级(Lock Escalation / Biased Locking → Lightweight Lock → Heavyweight Lock)

JVM锁优化的核心机制:从JDK 6开始,synchronized引入了锁升级机制,避免一上来就使用重量级锁(操作系统的互斥量,需要用户态到内核态切换,开销大),而是根据竞争激烈程度动态调整锁的状态。

锁的状态(级别从低到高):

  1. 无锁→ 2.偏向锁→ 3.轻量级锁→ 4.重量级锁

锁可以升级,但不能降级(偏向锁→轻量级→重量级单向)

(1)偏向锁(Biased Locking)
  • 场景:锁被同一个线程反复获取,没有竞争
  • 原理:第一次获取锁时,在对象头的Mark Word中记录该线程ID。后续该线程再进入同步块时,只需检查线程ID是否为当前线程,无需CAS操作
  • 撤销:当另一个线程来竞争时,偏向锁需要撤销(在全局安全点执行),可能升级为轻量级锁
(2)轻量级锁(Lightweight Locking)
  • 场景:少量线程交替持有锁,没有实际阻塞
  • 原理:线程在执行同步块前,在当前线程栈帧中创建锁记录(Lock Record),通过CAS将对象头的Mark Word替换为指向锁记录的指针。成功则获取锁,失败则说明有竞争
  • 特点:未获取锁的线程会自旋(CAS重试),不自旋失败后才膨胀为重量级锁
(3)重量级锁(Heavyweight Locking)
  • 场景:多条线程竞争激烈,自旋等待时间过长
  • 原理:锁膨胀为重量级锁后,对象头的Mark Word指向一个monitor对象(ObjectMonitor)
  • 特点:未获取到锁的线程会阻塞(进入等待队列),由操作系统调度,涉及用户态到内核态切换,开销最大

在使用synchronized API的时候,发生了什么事情(锁升级过程全流程)

用一个简单例子说明:

privatefinalObjectlock=newObject();publicvoidmethod(){synchronized(lock){// 临界区代码}}

执行流程:

  1. 创建对象lock时
    对象头Mark Word处于无锁状态(锁标志位01,偏向锁标志位0,表示暂时未启动偏向)

  2. 第一次线程T1进入synchronized块

    • JVM检查偏向锁是否启用(JVM默认启动偏向锁,但有延迟,默认4秒)
    • 如果启用并且没有竞争 → 进入偏向锁模式
      Mark Word中记录T1的线程ID,锁标志位改为偏向锁(01,偏向标志位=1)
    • 此后T1再次进入该同步块,只需检查线程ID是否匹配,不再CAS
  3. 线程T2来竞争锁(此时锁还在T1手中)

    • T2发现Mark Word中已经有T1的线程ID → 偏向锁需要撤销
    • 全局安全点(SafePoint)暂停T1线程,检查T1是否还存活
    • 如果T1已经退出同步块 → 偏向锁撤销,回到无锁状态,然后T2获得偏向锁
    • 如果T1仍在同步块内 → 偏向锁升级为轻量级锁
  4. 轻量级锁的竞争

    • T1和T2都在各自线程栈帧中创建锁记录(Lock Record)
    • 通过CAS尝试将对象头的Mark Word指向自己的锁记录
    • 成功者(T1)持有锁,失败者(T2)自旋(默认自旋次数或自适应自旋)
  5. 自旋一定次数后仍未获得锁→ 锁膨胀为重量级锁

    • JVM为lock对象分配一个ObjectMonitor(包含EntryList、WaitSet等)
    • 未获得锁的线程(T2等)挂起,进入操作系统的阻塞状态
    • 后续所有线程获取锁都需要通过monitor的enter/exit机制

API调用层面的统一性:
无论锁处于什么级别,synchronized代码块在Java源码层面写法完全一样。JVM内部会根据运行时竞争情况自动选择锁策略,对程序员透明。

补充:JVM参数控制锁升级(了解即可)

参数作用
-XX:+UseBiasedLocking开启偏向锁(JDK6+默认开启)
-XX:BiasedLockingStartupDelay=0关闭偏向锁启动延迟
-XX:-UseBiasedLocking关闭偏向锁,直接进入轻量级锁

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/6 17:05:45

如何快速打造完美暗黑2角色:5分钟掌握d2s存档编辑器的终极技巧

如何快速打造完美暗黑2角色:5分钟掌握d2s存档编辑器的终极技巧 【免费下载链接】d2s-editor 项目地址: https://gitcode.com/gh_mirrors/d2/d2s-editor 还在为暗黑破坏神2的装备掉落而烦恼吗?想要快速体验不同职业的终极Build吗?今天…

作者头像 李华
网站建设 2026/5/6 17:01:36

5分钟精通NSC_BUILDER:Switch游戏文件批量处理终极指南

5分钟精通NSC_BUILDER:Switch游戏文件批量处理终极指南 【免费下载链接】NSC_BUILDER Nintendo Switch Cleaner and Builder. A batchfile, python and html script based in hacbuild and Nuts python libraries. Designed initially to erase titlerights encrypt…

作者头像 李华
网站建设 2026/5/6 17:00:32

医学影像AI革命:MedSAM如何重塑精准分割新范式

医学影像AI革命:MedSAM如何重塑精准分割新范式 【免费下载链接】MedSAM Segment Anything in Medical Images 项目地址: https://gitcode.com/gh_mirrors/me/MedSAM MedSAM(Segment Anything in Medical Images)是一款专为医学影像分割…

作者头像 李华
网站建设 2026/5/6 16:58:27

Minecraft存档修复完全指南:Region Fixer技术解析与实战应用

Minecraft存档修复完全指南:Region Fixer技术解析与实战应用 【免费下载链接】Minecraft-Region-Fixer Python script to fix some of the problems of the Minecraft save files (region files, *.mca). 项目地址: https://gitcode.com/gh_mirrors/mi/Minecraft-…

作者头像 李华
网站建设 2026/5/6 16:57:30

BurpSuite汉化:让安全测试不再有语言障碍

BurpSuite汉化:让安全测试不再有语言障碍 【免费下载链接】BurpSuiteCN-Release BurpSuite汉化发布 项目地址: https://gitcode.com/gh_mirrors/bu/BurpSuiteCN-Release 你是不是也曾在Burp Suite的英文界面中迷失方向,面对密密麻麻的英文术语感…

作者头像 李华