元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
JVM架构
类加载器机制
运行时数据区
执行引擎工作原理
JIT编译器优化
▶
内存管理
垃圾回收算法
分代收集机制
内存分配策略
内存泄漏诊断
▶
并发编程
线程池实现原理
synchronized锁优化
AQS框架解析
并发集合类原理
▶
字节码技术
字节码指令集解析
ASM操作指南
动态代理实现
字节码验证机制
▶
性能调优
JVM参数解析
GC日志分析
堆内存诊断
JIT性能优化
发布时间:
2025-03-22 09:33
↑
☰
# Java Synchronized锁优化 Synchronized是Java中最基本的同步机制,随着JVM的发展,synchronized的性能得到了很大的优化。本文将详细介绍synchronized的工作原理、优化机制以及最佳实践。 ## 基础概念 ### 1. Synchronized的使用方式 ```java public class SynchronizedDemo { // 1. 修饰实例方法 public synchronized void instanceMethod() { // 同步代码 } // 2. 修饰静态方法 public static synchronized void staticMethod() { // 同步代码 } // 3. 修饰代码块 public void blockMethod() { synchronized(this) { // 同步代码 } } } ``` 使用场景: 1. 实例方法同步 2. 静态方法同步 3. 代码块同步 ### 2. 实现原理 ```java public class SynchronizedPrincipleDemo { private static Object lock = new Object(); public static void main(String[] args) { // 反编译后可以看到monitorenter和monitorexit指令 synchronized(lock) { System.out.println("同步代码块"); } } } ``` 底层实现: - monitorenter:进入同步块 - monitorexit:退出同步块 - 对象头中的Mark Word存储锁信息 ## 锁优化 ### 1. 锁的升级过程 ```java public class LockUpgradeDemo { private static final int ITERATIONS = 1000000; private static Object lock = new Object(); private static int counter = 0; public static void main(String[] args) { // 演示锁升级 Thread t1 = new Thread(() -> { for (int i = 0; i < ITERATIONS; i++) { synchronized(lock) { counter++; } } }); Thread t2 = new Thread(() -> { for (int i = 0; i < ITERATIONS; i++) { synchronized(lock) { counter++; } } }); t1.start(); t2.start(); } } ``` 锁升级过程: 1. 无锁 → 偏向锁 2. 偏向锁 → 轻量级锁 3. 轻量级锁 → 重量级锁 ### 2. 偏向锁 ```java public class BiasedLockDemo { private static Object lock = new Object(); public static void main(String[] args) { // -XX:+UseBiasedLocking // -XX:BiasedLockingStartupDelay=0 // 同一个线程多次获取锁 for (int i = 0; i < 100; i++) { synchronized(lock) { // 执行同步代码 System.out.println("第" + (i + 1) + "次获取锁"); } } } } ``` 偏向锁特点: - 针对同一线程多次获取同一把锁 - 只有第一次需要CAS操作 - 后续获取锁时只需要比较ThreadID ### 3. 轻量级锁 ```java public class LightweightLockDemo { private static final int THREADS = 2; private static Object lock = new Object(); public static void main(String[] args) { // 创建多个线程交替获取锁 for (int i = 0; i < THREADS; i++) { new Thread(() -> { for (int j = 0; j < 100; j++) { synchronized(lock) { System.out.println(Thread.currentThread().getName() + ": 获取锁"); } } }, "Thread-" + i).start(); } } } ``` 轻量级锁优化: - 使用CAS操作替代互斥量 - 适用于线程交替执行同步块 - 竞争激烈时升级为重量级锁 ## 锁消除 ### 1. JIT优化 ```java public class LockEliminationDemo { public static String concatString(String s1, String s2, String s3) { // JIT可能会优化掉这里的锁 StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); sb.append(s3); return sb.toString(); } public static void main(String[] args) { // -XX:+DoEscapeAnalysis // -XX:+EliminateLocks for (int i = 0; i < 1000000; i++) { concatString("Hello", "World", "!"); } } } ``` 锁消除条件: - 逃逸分析证明锁对象不会被其他线程访问 - 代码在JIT编译时优化 ### 2. 锁粗化 ```java public class LockCoarseningDemo { private static final Object lock = new Object(); public static void main(String[] args) { // 锁粗化前 for (int i = 0; i < 100; i++) { synchronized(lock) { System.out.println(i); } } // 锁粗化后 synchronized(lock) { for (int i = 0; i < 100; i++) { System.out.println(i); } } } } ``` 锁粗化优化: - 合并相邻的同步块 - 减少锁的请求次数 - 降低同步开销 ## 实践应用 ### 1. 性能监控 ```java public class LockMonitorDemo { public static void main(String[] args) { // 使用JMX监控锁的竞争情况 ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); new Thread(() -> { while (true) { long[] threadIds = threadBean.findMonitorDeadlockedThreads(); if (threadIds != null) { ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds); System.out.println("检测到死锁:"); for (ThreadInfo info : threadInfos) { System.out.println(info); } } try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } } ``` 监控指标: 1. 锁的争用情况 2. 等待线程数量 3. 死锁检测 ### 2. 最佳实践 ```java public class SynchronizedBestPracticeDemo { // 1. 缩小同步范围 private final Map<String, String> map = new ConcurrentHashMap<>(); public void goodPractice() { // 只同步必要的代码块 String value = heavyComputation(); synchronized(this) { map.put("key", value); } } // 2. 选择合适的锁粒度 private final Object[] locks = new Object[10]; public SynchronizedBestPracticeDemo() { for (int i = 0; i < locks.length; i++) { locks[i] = new Object(); } } public void fineLock(int id) { synchronized(locks[id % locks.length]) { // 更细粒度的锁 } } private String heavyComputation() { // 模拟耗时计算 return "result"; } } ``` 实践建议: 1. 缩小同步范围 2. 选择合适的锁粒度 3. 避免锁嵌套 4. 优先使用并发容器 ## 性能对比 ### 1. 不同锁的性能测试 ```java public class LockPerformanceDemo { private static final int THREADS = 10; private static final int ITERATIONS = 100000; public static void main(String[] args) throws InterruptedException { // 1. 偏向锁 testBiasedLock(); // 2. 轻量级锁 testLightweightLock(); // 3. 重量级锁 testHeavyweightLock(); } private static void testBiasedLock() throws InterruptedException { Object lock = new Object(); long start = System.nanoTime(); Thread t = new Thread(() -> { for (int i = 0; i < ITERATIONS; i++) { synchronized(lock) { // 同一线程重复获取锁 } } }); t.start(); t.join(); System.out.println("偏向锁耗时:" + (System.nanoTime() - start) / 1000000 + "ms"); } private static void testLightweightLock() throws InterruptedException { Object lock = new Object(); Thread[] threads = new Thread[2]; long start = System.nanoTime(); for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < ITERATIONS; j++) { synchronized(lock) { // 线程交替获取锁 } } }); } for (Thread t : threads) t.start(); for (Thread t : threads) t.join(); System.out.println("轻量级锁耗时:" + (System.nanoTime() - start) / 1000000 + "ms"); } private static void testHeavyweightLock() throws InterruptedException { Object lock = new Object(); Thread[] threads = new Thread[THREADS]; long start = System.nanoTime(); for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < ITERATIONS; j++) { synchronized(lock) { // 多线程竞争锁 } } }); } for (Thread t : threads) t.start(); for (Thread t : threads) t.join(); System.out.println("重量级锁耗时:" + (System.nanoTime() - start) / 1000000 + "ms"); } } ``` 性能比较: 1. 偏向锁:单线程性能最好 2. 轻量级锁:适中竞争性能好 3. 重量级锁:高竞争下性能较差 ## 总结 通过本文,我们详细了解了synchronized的优化机制: 1. 锁的升级过程 - 偏向锁 - 轻量级锁 - 重量级锁 2. JVM优化 - 锁消除 - 锁粗化 - 逃逸分析 3. 实践建议 - 合理使用同步范围 - 选择适当的锁粒度 - 避免不必要的同步 在实际开发中,我们应该: 1. 理解synchronized的工作原理 2. 合理使用锁优化机制 3. 注意锁的性能开销 4. 遵循最佳实践原则 掌握这些知识对于开发高性能的并发程序至关重要。