获课:666it.top/13660/
Java锁优化终极奥义:从synchronized到StampedLock
一、Java锁机制演进全景
Java并发编程中的锁机制经历了从简单到复杂、从重量级到轻量级的演进过程:
synchronized:Java最基础的同步机制,属于JVM内置锁
ReentrantLock:JDK5引入的显式锁,提供更灵活的锁操作
ReadWriteLock:读写分离锁,优化读多写少场景
StampedLock:JDK8引入的改进版读写锁,支持乐观读
二、synchronized深度解析
实现原理
synchronized关键字底层属于JVM层面,通过monitor对象实现:
每个Java对象都关联一个monitor(监视器锁)
进入同步块时执行monitorenter指令
退出同步块时执行monitorexit指令
锁升级过程
JDK6后synchronized实现了锁升级优化:
无锁状态:初始状态
偏向锁(MarkWord标记101):偏向第一个获取锁的线程
轻量级锁(CAS自旋):短时间竞争时使用
重量级锁:竞争激烈时升级为操作系统级互斥量
使用场景
Java
// 对象锁
public synchronized void method() {...}
// 类锁
public static synchronized void staticMethod() {...}
// 同步代码块
synchronized(lockObject) {
// 临界区
}
三、显式锁ReentrantLock进阶
核心特性
可重入性:同一线程可重复获取锁
公平/非公平选择:构造函数指定
可中断:lockInterruptibly()
超时尝试:tryLock(long timeout, TimeUnit unit)
性能对比
在JDK17、8核CPU测试环境下:
synchronized:中等吞吐量
ReentrantLock:高吞吐量
最佳实践
Java
Lock lock = new ReentrantLock();
try {
lock.lock();
// 临界区
} finally {
lock.unlock();
}
四、读写锁ReadWriteLock优化
适用场景
特别适合读多写少的场景,如:
配置中心
缓存系统
数据看板
实现原理
读锁:共享锁,允许多线程并发读
写锁:独占锁,互斥读写操作
Java
ReadWriteLock rwLock = new ReentrantReadWriteLock();
Lock readLock = rwLock.readLock();
Lock writeLock = rwLock.writeLock();
五、StampedLock黑科技
三大模式
写锁:独占锁,类似ReentrantLock
悲观读锁:类似ReadWriteLock的读锁
乐观读:不加锁,通过版本号校验
性能优势
测试数据显示:
极低延迟
高吞吐量
但不支持重入
实战示例
Java
StampedLock lock = new StampedLock();
// 乐观读
long stamp = lock.tryOptimisticRead();
// 读操作...
if (!lock.validate(stamp)) {
// 升级为悲观读
stamp = lock.readLock();
try {
// 重新读
} finally {
lock.unlockRead(stamp);
}
}
// 写锁
long stamp = lock.writeLock();
try {
// 写操作
} finally {
lock.unlockWrite(stamp);
}
六、锁优化实战技巧
1. 锁粒度控制
尽可能减小同步代码块范围
分离锁(lock splitting)技术
锁分段(ConcurrentHashMap实现原理)
2. 避免死锁
按固定顺序获取锁
使用tryLock设置超时
静态代码分析工具检测
3. 锁消除
JVM通过逃逸分析消除不必要的锁:
Java
public String concat(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
// JVM会消除StringBuffer的同步锁
4. 锁粗化
将连续的锁请求合并:
Java
// 优化前
for (int i = 0; i < 100; i++) {
synchronized(lock) {
// 操作
}
}
// 优化后
synchronized(lock) {
for (int i = 0; i < 100; i++) {
// 操作
}
}
七、面试高频问题解析
Q1:synchronized和ReentrantLock区别?
实现:JVM内置 vs JDK实现
功能:ReentrantLock支持公平锁、条件变量等
性能:JDK6后两者性能接近
使用:隐式自动释放 vs 显式手动释放
Q2:如何选择锁类型?
低竞争:乐观锁(StampedLock乐观读)
高竞争:悲观锁
读多写少:ReadWriteLock/StampedLock
写多:ReentrantLock
Q3:StampedLock的陷阱?
不支持重入
乐观读后需要校验
容易导致死锁(需严格遵循锁协议)
八、性能对比数据
锁类型
吞吐量(ops/ms)
延迟
重入支持
synchronized
中等
中等
支持
ReentrantLock
高
低
支持
ReadWriteLock
极高
低
支持
StampedLock
极高
极低
不支持
九、终极选择指南
简单同步:优先考虑synchronized
高级功能需求:选择ReentrantLock
读多写少:ReadWriteLock或StampedLock
极致性能:StampedLock(注意正确使用)
记住:没有最好的锁,只有最适合场景的锁。理解各锁的特性,根据实际业务场景做出合理选择,才是真正的"锁优化终极奥义"。
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传