
一、锁优化的核心基石对象头与内存布局在JVM中synchronized的锁状态完全存储在Java对象的对象头中理解对象头的结构是拆解锁膨胀机制的前提。64位JVM默认开启压缩指针时对象头由Mark Word标记字段和Klass Pointer类型指针两部分组成数组对象还会额外存储数组长度。其中Mark Word是锁实现的核心固定占用8字节存储了对象的哈希码、分代年龄、锁状态、线程ID等核心信息。1.1 Mark Word的状态结构Mark Word的存储结构会随着锁状态的变化动态复用不同锁状态下的位分配如下表所示锁状态高25位31位分代年龄1位偏向锁位2位锁标记位无锁未使用分代年龄001偏向锁持有锁的线程ID分代年龄101轻量级锁指向栈中LockRecord的指针--00重量级锁指向Monitor对象的指针--10GC标记空--11核心规则锁标记位是判断锁状态的核心依据其中无锁与偏向锁共用01标记位通过偏向锁位做二次区分。1.2 管程模型Monitor重量级锁的底层实现依赖于Monitor管程对象每个重量级锁都会关联一个独立的Monitor其核心结构包含三个关键部分_owner指向当前持有锁的线程_EntryList入口集存储竞争锁失败被阻塞的线程_WaitSet等待集存储调用wait()方法进入等待状态的线程Monitor的底层依赖操作系统的互斥量mutex实现涉及用户态与内核态的切换单次切换的开销约为数千纳秒这也是重量级锁性能开销大的核心原因。二、锁膨胀全链路流程与底层实现锁膨胀的本质是JVM针对不同的线程竞争场景自动选择开销最低的锁实现当竞争加剧时锁会从低开销状态逐步向高开销状态升级。整个流程遵循固定的升级路径仅在GC安全点会发生锁降级。2.1 锁膨胀全流程2.2 各锁状态的底层实现与适用场景2.2.1 无锁状态无锁状态下对象的Mark Word仅存储分代年龄、未使用的高位空间偏向锁位为0锁标记位为01。此时对象没有被任何线程加锁是所有对象的初始状态。2.2.2 偏向锁偏向锁的核心设计理念是无竞争场景下消除同步操作的所有开销。其适用场景为单线程反复获取同一把锁无多线程竞争。核心原理第一个获取锁的线程会通过CAS将自己的线程ID写入对象的Mark Word将对象标记为偏向当前线程。后续该线程再次获取锁时仅需比对Mark Word中的线程ID无需任何CAS操作开销仅为几次内存读取和无锁操作几乎无差别。可重入实现线程重入时会在当前栈帧中创建一个无内容的Lock Record作为重入计数的凭证无需执行CAS操作重入次数由栈中Lock Record的数量决定。偏向撤销当有第二个线程尝试竞争该锁时会触发偏向撤销。偏向撤销必须在GC安全点执行会暂停所有正在运行的线程校验持有偏向锁的线程是否存活若线程已退出则重置对象为无锁状态若线程仍存活则升级为轻量级锁。关键特性JDK15及以上版本默认关闭偏向锁需通过JVM参数-XX:UseBiasedLocking -XX:BiasedLockingStartupDelay0手动开启。高并发场景下偏向撤销的STW开销远大于偏向锁带来的收益因此高并发系统不建议开启。2.2.3 轻量级锁轻量级锁的核心设计理念是低竞争场景下通过用户态CAS避免内核态的开销。其适用场景为多个线程交替获取锁同一时刻无多线程同时竞争。加锁流程线程在当前栈帧中创建名为Lock Record的空间用于存储对象当前Mark Word的拷贝官方称为Displaced Mark Word。线程通过CAS尝试将对象的Mark Word替换为指向当前栈中Lock Record的指针。若CAS成功当前线程获取轻量级锁将锁标记位设置为00。若CAS失败说明存在竞争线程会进入自适应自旋阶段反复尝试CAS获取锁。自适应自旋自旋的次数不是固定值JVM会根据同一个锁上一次的自旋成功率与持有锁线程的状态动态调整。若上一次自旋成功获取了锁本次会增加自旋次数若上一次自旋失败本次会直接跳过自旋升级为重量级锁。可重入实现线程每次重入都会在栈帧中创建一个新的Lock Record存储Displaced Mark Word重入次数由栈中Lock Record的数量决定。锁释放线程每次退出同步块都会释放一个Lock Record当栈中所有Lock Record都被释放后通过CAS将Displaced Mark Word还原到对象头中。若还原时存在竞争锁会直接膨胀为重量级锁。2.2.4 重量级锁重量级锁是锁膨胀的最终阶段核心设计理念是高竞争场景下通过内核态互斥量保证线程安全避免CPU空转。其适用场景为多线程同时竞争同一把锁竞争激烈。核心原理锁膨胀为重量级锁时JVM会为对象创建关联的Monitor对象将对象的Mark Word替换为指向Monitor的指针锁标记位设置为10。竞争失败的线程会被加入Monitor的EntryList进入内核态阻塞状态直到持有锁的线程释放锁后被唤醒。可重入实现Monitor对象中维护了_recursions字段记录锁的重入次数线程每次重入该字段加1每次解锁减1减至0时才会真正释放锁唤醒EntryList中的等待线程。内存语义重量级锁的加锁与解锁操作具备完整的Happens-Before语义解锁操作会将线程工作内存中的所有修改刷新到主内存加锁操作会将工作内存失效从主内存中读取最新数据保证多线程之间的可见性、原子性与有序性。2.3 锁降级机制很多资料中提到锁膨胀是单向不可逆的这个说法并不准确。JVM会在GC安全点对无竞争的锁进行降级若重量级锁关联的Monitor没有线程持有也没有线程在EntryList中等待GC时会将其降级为无锁状态。轻量级锁若没有线程竞争GC时也会重置为无锁状态。 锁降级仅发生在GC过程中不会在锁释放的过程中实时发生因此常规业务场景中我们仍可以认为锁的升级是单向的。三、JVM内置锁优化补充机制除了锁膨胀机制JVM还提供了四项核心的锁优化技术进一步降低同步操作的性能开销。3.1 锁消除锁消除是JIT编译器的优化技术核心逻辑是通过逃逸分析判断某把锁的对象仅能被一个线程访问不存在多线程竞争的可能JIT会直接消除该锁的同步操作避免无意义的加锁解锁开销。package com.jam.demo; import lombok.extern.slf4j.Slf4j; /** * 锁消除演示示例 * author ken */ Slf4j public class LockEliminationDemo { /** * 锁消除场景演示 * StringBuffer的append方法是synchronized修饰的 * 但sb是局部变量,不会逃逸出当前方法,不存在多线程竞争 * JIT编译时会直接消除append方法的锁操作 */ public String lockEliminationTest() { StringBuffer sb new StringBuffer(); sb.append(a); sb.append(b); sb.append(c); return sb.toString(); } public static void main(String[] args) { LockEliminationDemo demo new LockEliminationDemo(); // 触发JIT编译 for (int i 0; i 100000; i) { demo.lockEliminationTest(); } } }锁消除的开启需要满足两个条件JIT编译开启默认开启、逃逸分析开启JVM参数-XX:DoEscapeAnalysis默认开启。3.2 锁粗化锁粗化的核心逻辑是当JIT检测到一系列连续的加锁解锁操作都是针对同一个锁对象会将锁的范围粗化到整个操作序列的外部避免频繁的加锁解锁带来的性能开销。package com.jam.demo; import lombok.extern.slf4j.Slf4j; /** * 锁粗化演示示例 * author ken */ Slf4j public class LockCoarseningDemo { private final StringBuffer sb new StringBuffer(); /** * 锁粗化场景演示 * 循环内反复对同一个对象加锁解锁 * JIT会将锁粗化到循环外部,仅加锁解锁一次 */ public void lockCoarseningTest() { for (int i 0; i 100; i) { sb.append(i); } } public static void main(String[] args) { LockCoarseningDemo demo new LockCoarseningDemo(); // 触发JIT编译 for (int i 0; i 100000; i) { demo.lockCoarseningTest(); } } }锁粗化通过JVM参数-XX:EliminateLocks开启默认开启。3.3 自适应自旋自适应自旋在轻量级锁章节已经提及核心是JVM会根据锁的历史竞争情况动态调整自旋次数避免固定自旋次数带来的CPU空转或频繁内核态切换问题。该特性通过-XX:UseAdaptiveSpinning开启默认开启不建议手动修改。3.4 逃逸分析逃逸分析是所有锁优化的基础JVM通过逃逸分析判断对象的作用范围不逃逸对象仅在当前方法内使用不会被其他线程访问。方法逃逸对象被传递到其他方法中但不会被外部线程访问。线程逃逸对象被外部线程访问存在多线程竞争的可能。 只有不逃逸的对象才会触发锁消除优化。逃逸分析通过-XX:DoEscapeAnalysis开启默认开启。四、锁膨胀可视化演示与代码实战本节通过JOLJava Object Layout工具可视化展示锁膨胀的完整过程。4.1 环境依赖配置首先在maven的pom.xml中添加所需依赖?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.4/version relativePath/ /parent groupIdcom.jam.demo/groupId artifactIdjvm-lock-demo/artifactId version1.0.0/version properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding mybatis-plus.version3.5.6/mybatis-plus.version fastjson2.version2.0.52/fastjson2.version guava.version33.1.0-jre/guava.version jol.version0.17/jol.version jmh.version1.37/jmh.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-starter-webmvc-ui/artifactId version2.5.0/version /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version${mybatis-plus.version}/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.32/version scopeprovided/scope /dependency dependency groupIdcom.alibaba.fastjson2/groupId artifactIdfastjson2/artifactId version${fastjson2.version}/version /dependency dependency groupIdcom.google.guava/groupId artifactIdguava/artifactId version${guava.version}/version /dependency dependency groupIdorg.openjdk.jol/groupId artifactIdjol-core/artifactId version${jol.version}/version /dependency dependency groupIdorg.openjdk.jmh/groupId artifactIdjmh-core/artifactId version${jmh.version}/version /dependency dependency groupIdorg.openjdk.jmh/groupId artifactIdjmh-generator-annprocess/artifactId version${jmh.version}/version scopeprovided/scope /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.13.0/version configuration source17/source target17/target /configuration /plugin /plugins /build /project4.2 锁膨胀全流程可视化代码package com.jam.demo; import org.openjdk.jol.info.ClassLayout; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; /** * 锁膨胀全流程可视化演示 * author ken */ Slf4j public class LockInflationDemo { private static final Object lockObj new Object(); public static void main(String[] args) throws InterruptedException { log.info(1. 无锁状态,对象头信息:); printObjectHead(); Thread.sleep(1000); // 单线程加锁,演示轻量级锁(JDK17默认关闭偏向锁) synchronized (lockObj) { log.info(2. 单线程持有锁,轻量级锁状态,对象头信息:); printObjectHead(); } log.info(3. 轻量级锁释放后,对象头信息:); printObjectHead(); Thread.sleep(1000); // 多线程竞争,演示膨胀为重量级锁 CountDownLatch latch new CountDownLatch(2); Thread thread1 new Thread(() - { for (int i 0; i 100; i) { synchronized (lockObj) { if (i 50) { log.info(4. 多线程竞争下,重量级锁状态,对象头信息:); printObjectHead(); } } } latch.countDown(); }); Thread thread2 new Thread(() - { for (int i 0; i 100; i) { synchronized (lockObj) { } } latch.countDown(); }); thread1.start(); thread2.start(); latch.await(); Thread.sleep(1000); log.info(5. 重量级锁释放后,对象头信息:); printObjectHead(); } /** * 打印对象头信息 */ private static void printObjectHead() { System.out.println(ClassLayout.parseInstance(lockObj).toPrintable()); } }运行说明若需演示偏向锁需添加JVM启动参数-XX:UseBiasedLocking -XX:BiasedLockingStartupDelay0控制台输出的对象头中前8字节为Mark Word可通过锁标记位判断当前锁状态。4.3 高并发场景锁性能基准测试通过JMH官方基准测试工具对比不同锁实现的吞吐量性能代码如下package com.jam.demo; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.LongAdder; import java.util.concurrent.locks.ReentrantLock; /** * 高并发锁性能基准测试 * author ken */ BenchmarkMode(Mode.Throughput) OutputTimeUnit(TimeUnit.MILLISECONDS) Warmup(iterations 3, time 1, timeUnit TimeUnit.SECONDS) Measurement(iterations 5, time 1, timeUnit TimeUnit.SECONDS) Fork(1) Threads(10) State(Scope.Benchmark) public class LockPerformanceBenchmark { private int syncCount 0; private final Object lockObj new Object(); private final AtomicInteger atomicCount new AtomicInteger(0); private final LongAdder adderCount new LongAdder(); private final ReentrantLock reentrantLock new ReentrantLock(); private int lockCount 0; Benchmark public void syncLockTest() { synchronized (lockObj) { syncCount; } } Benchmark public void atomicIntegerTest() { atomicCount.incrementAndGet(); } Benchmark public void longAdderTest() { adderCount.increment(); } Benchmark public void reentrantLockTest() { reentrantLock.lock(); try { lockCount; } finally { reentrantLock.unlock(); } } public static void main(String[] args) throws RunnerException { Options options new OptionsBuilder() .include(LockPerformanceBenchmark.class.getSimpleName()) .build(); new Runner(options).run(); } }测试结论无竞争场景下偏向锁性能最优与无锁操作几乎无差别其次是轻量级锁、AtomicInteger、ReentrantLock。低竞争场景下轻量级锁性能优于重量级锁AtomicInteger性能优于synchronized与ReentrantLock。高竞争场景下LongAdder性能最优其次是AtomicIntegerReentrantLock与重量级锁synchronized性能接近。五、高并发业务场景锁调优实战本节以电商核心的库存扣减场景为例结合MyBatisPlus与MySQL8.0演示高并发场景下的锁调优方案。5.1 数据库表结构CREATE TABLE t_inventory ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, sku_id bigint NOT NULL COMMENT 商品SKU ID, stock_num int NOT NULL DEFAULT 0 COMMENT 库存数量, version int NOT NULL DEFAULT 0 COMMENT 乐观锁版本号, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_sku_id (sku_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci COMMENT商品库存表;5.2 实体类定义package com.jam.demo.entity; import com.baomidou.mybatisplus.annotation.*; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; /** * 库存实体类 * author ken */ Data TableName(t_inventory) Schema(description 商品库存实体) public class Inventory { TableId(type IdType.AUTO) Schema(description 主键ID, example 1) private Long id; Schema(description 商品SKU ID, example 1001) private Long skuId; Schema(description 库存数量, example 1000) private Integer stockNum; Version Schema(description 乐观锁版本号, example 0) private Integer version; TableField(fill FieldFill.INSERT) Schema(description 创建时间) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) Schema(description 更新时间) private LocalDateTime updateTime; }5.3 Mapper层定义package com.jam.demo.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.jam.demo.entity.Inventory; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; /** * 库存Mapper接口 * author ken */ public interface InventoryMapper extends BaseMapperInventory { /** * 悲观锁扣减库存 * param skuId 商品SKU ID * param num 扣减数量 * return 影响行数 */ Update(UPDATE t_inventory SET stock_num stock_num - #{num} WHERE sku_id #{skuId} AND stock_num #{num}) int deductStockByPessimisticLock(Param(skuId) Long skuId, Param(num) Integer num); }5.4 Service层实现package com.jam.demo.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.jam.demo.entity.Inventory; import com.jam.demo.mapper.InventoryMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.util.ObjectUtils; /** * 库存服务实现类 * author ken */ Slf4j Service RequiredArgsConstructor public class InventoryService { private final InventoryMapper inventoryMapper; private final PlatformTransactionManager transactionManager; /** * 乐观锁扣减库存 * param skuId 商品SKU ID * param deductNum 扣减数量 * return 扣减结果 */ public boolean deductStockByOptimisticLock(Long skuId, Integer deductNum) { if (ObjectUtils.isEmpty(skuId) || ObjectUtils.isEmpty(deductNum) || deductNum 0) { log.error(库存扣减参数异常,skuId:{},deductNum:{}, skuId, deductNum); return false; } // 编程式事务定义 DefaultTransactionDefinition def new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); TransactionStatus status transactionManager.getTransaction(def); try { // 查询库存信息 Inventory inventory inventoryMapper.selectOne( new LambdaQueryWrapperInventory() .eq(Inventory::getSkuId, skuId) ); if (ObjectUtils.isEmpty(inventory)) { log.error(商品库存不存在,skuId:{}, skuId); transactionManager.rollback(status); return false; } if (inventory.getStockNum() deductNum) { log.warn(商品库存不足,skuId:{},currentStock:{},deductNum:{}, skuId, inventory.getStockNum(), deductNum); transactionManager.rollback(status); return false; } // 乐观锁更新,版本号自动递增 LambdaUpdateWrapperInventory updateWrapper new LambdaUpdateWrapper(); updateWrapper.eq(Inventory::getId, inventory.getId()) .eq(Inventory::getVersion, inventory.getVersion()) .setSql(stock_num stock_num - deductNum); int updateRows inventoryMapper.update(null, updateWrapper); if (updateRows 0) { transactionManager.commit(status); log.info(乐观锁库存扣减成功,skuId:{},deductNum:{}, skuId, deductNum); return true; } else { transactionManager.rollback(status); log.warn(乐观锁更新失败,存在并发竞争,skuId:{}, skuId); return false; } } catch (Exception e) { transactionManager.rollback(status); log.error(库存扣减异常,skuId:{}, skuId, e); return false; } } /** * 悲观锁扣减库存 * param skuId 商品SKU ID * param deductNum 扣减数量 * return 扣减结果 */ public boolean deductStockByPessimisticLock(Long skuId, Integer deductNum) { if (ObjectUtils.isEmpty(skuId) || ObjectUtils.isEmpty(deductNum) || deductNum 0) { log.error(库存扣减参数异常,skuId:{},deductNum:{}, skuId, deductNum); return false; } DefaultTransactionDefinition def new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); TransactionStatus status transactionManager.getTransaction(def); try { int updateRows inventoryMapper.deductStockByPessimisticLock(skuId, deductNum); if (updateRows 0) { transactionManager.commit(status); log.info(悲观锁库存扣减成功,skuId:{},deductNum:{}, skuId, deductNum); return true; } else { transactionManager.rollback(status); log.warn(库存不足,扣减失败,skuId:{},deductNum:{}, skuId, deductNum); return false; } } catch (Exception e) { transactionManager.rollback(status); log.error(库存扣减异常,skuId:{}, skuId, e); return false; } } }5.5 Controller层实现package com.jam.demo.controller; import com.jam.demo.service.InventoryService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * 库存操作接口 * author ken */ RestController RequestMapping(/inventory) RequiredArgsConstructor Tag(name 库存管理, description 商品库存扣减相关接口) public class InventoryController { private final InventoryService inventoryService; PostMapping(/deduct/optimistic) Operation(summary 乐观锁扣减库存, description 高并发场景推荐使用,无锁阻塞开销) public boolean deductByOptimisticLock( Parameter(description 商品SKU ID, required true) RequestParam Long skuId, Parameter(description 扣减数量, required true) RequestParam Integer deductNum) { return inventoryService.deductStockByOptimisticLock(skuId, deductNum); } PostMapping(/deduct/pessimistic) Operation(summary 悲观锁扣减库存, description 并发量较低、数据一致性要求极高的场景使用) public boolean deductByPessimisticLock( Parameter(description 商品SKU ID, required true) RequestParam Long skuId, Parameter(description 扣减数量, required true) RequestParam Integer deductNum) { return inventoryService.deductStockByPessimisticLock(skuId, deductNum); } }5.6 场景调优方案高并发秒杀场景优先使用乐观锁方案避免JVM锁与数据库行锁带来的阻塞开销同时结合预扣库存、库存分段、消息队列削峰等方案进一步降低锁竞争。低并发高一致性场景可使用悲观锁方案保证数据强一致性同时缩小锁的范围避免长事务持有锁。JVM锁调优避免在分布式场景下使用JVM锁分布式场景优先使用分布式锁如Redis分布式锁、Zookeeper分布式锁单机场景优先缩小锁的粒度与持有时间降低锁竞争的概率。六、易混淆技术点明确区分6.1 轻量级锁 ≠ 自旋锁轻量级锁是JVM定义的一种锁状态核心是通过用户态CAS实现同步自旋是锁竞争失败后的一种重试机制不仅轻量级锁会使用自旋重量级锁在进入内核态阻塞之前也会尝试自旋。自旋是一种优化手段不是锁的状态二者不能划等号。6.2 偏向锁撤销 ≠ 锁释放偏向锁撤销是指多线程竞争时取消对象的偏向状态将锁升级为轻量级锁的过程该过程需要在GC安全点执行会触发STW锁释放是线程执行完同步块主动释放锁的过程不会触发STW。二者是完全不同的操作不能混淆。6.3 用户态锁 vs 内核态锁用户态锁偏向锁、轻量级锁的实现完全在用户态完成不需要操作系统内核介入不会发生用户态与内核态的切换开销极低。内核态锁重量级锁依赖操作系统的互斥量实现线程的阻塞与唤醒都需要内核介入会发生用户态与内核态的切换开销极大。6.4 synchronized vs ReentrantLock特性synchronizedReentrantLock实现层面JVM层面实现,由字节码指令控制JDK层面实现,基于AQS框架锁优化支持锁膨胀、锁消除、锁粗化等全链路优化仅支持公平锁/非公平锁、可中断等特性可重入性支持,底层通过Mark Word/Monitor实现支持,底层通过AQS的state字段实现公平锁仅支持非公平锁支持公平锁与非公平锁,可通过构造方法指定高级特性无支持可中断获取锁、超时获取锁、多条件变量释放方式自动释放,异常时也会释放必须手动在finally块中释放,否则会造成死锁七、生产环境锁调优最佳实践7.1 锁竞争问题排查工具jstackJDK自带的线程堆栈分析工具可查看线程的锁持有状态、锁等待状态快速定位死锁与锁竞争问题。Arthas阿里开源的Java诊断工具可通过vmtool命令查看对象头的锁状态通过thread命令查看线程的锁竞争情况。JProfiler/AsyncProfiler性能分析工具可采集锁的持有时间、竞争次数定位性能瓶颈。7.2 核心调优原则优先无锁设计最优的锁优化永远是消除锁。通过ThreadLocal、不可变对象、无锁并发工具类如LongAdder、ConcurrentHashMap等方案避免锁竞争。缩小锁粒度仅对需要同步的代码块加锁避免对整个方法加锁减少锁的持有时间。降低锁的持有时间将耗时操作如IO操作、网络调用移出同步块避免持有锁的同时执行耗时操作加剧锁竞争。避免锁嵌套严格控制加锁顺序所有线程按照相同的顺序加锁避免死锁问题。合理选择锁类型单线程无竞争场景开启偏向锁获得最优性能。多线程交替加锁场景使用轻量级锁避免内核态开销。高并发竞争场景优先使用乐观锁、JUC并发工具类避免重量级锁。JVM参数调优高并发场景保持JDK17默认配置关闭偏向锁避免偏向撤销的STW开销。低延迟系统通过-XX:PreBlockSpin调整自旋次数减少内核态切换的概率不建议手动调整优先使用自适应自旋。开启逃逸分析与锁消除保持默认开启状态JIT会自动优化无意义的锁操作。7.3 分布式场景注意事项JVM锁仅能保证单机内的线程安全分布式场景下必须使用分布式锁避免出现数据不一致问题。分布式锁优先选择Redis Redlock、Zookeeper分布式锁等成熟方案同时保证锁的可重入性、超时释放、死锁预防等特性。八、总结JVM的锁膨胀机制本质上是JVM在性能与线程安全之间做的动态平衡针对不同的竞争场景提供了不同开销的锁实现。从无锁到偏向锁、轻量级锁、重量级锁每一次锁膨胀都是JVM针对竞争加剧做出的自适应调整。理解锁膨胀的底层逻辑不仅能打破对synchronized的刻板印象更能在开发中写出更高效的同步代码在生产环境出现锁竞争问题时快速定位根因给出针对性的调优方案。在高并发系统设计中我们需要始终记住锁优化的核心不是把锁的性能调到极致而是通过合理的架构设计从根源上消除锁竞争。