Java中的锁机制全解析:从synchronized到分布式锁
在多线程编程中,锁是保证线程安全的核心工具。本文将详解Java中常见的锁机制及其实际应用场景,帮助开发者选择最合适的锁方案。
一、内置锁:synchronized
原理
通过JVM内置的监视器锁(Monitor)实现,可修饰方法或代码块。
// 修饰方法
public synchronized void add() {// 线程安全操作
}// 修饰代码块
public void increment() {synchronized(this) {// 线程安全操作}
}
场景
-
单机简单同步:如计数器、对象状态变更
-
资源竞争低:性能要求不高的场景
二、显式锁:ReentrantLock
特性
-
可重入性
-
支持公平/非公平锁
-
尝试获取锁(tryLock)
-
可中断锁
ReentrantLock lock = new ReentrantLock();public void performTask() {lock.lock();try {// 临界区操作} finally {lock.unlock(); // 必须手动释放}
}
场景
-
复杂同步逻辑:需要尝试获取锁
if (lock.tryLock(1, TimeUnit.SECONDS)) {try {// 获取锁成功} finally {lock.unlock();}
}
-
公平性要求:防止线程饥饿
-
锁分离:配合Condition实现等待通知机制
三、读写锁:ReentrantReadWriteLock
原理
分离读锁(共享)和写锁(独占),提升读多写少场景的性能。
ReadWriteLock rwLock = new ReentrantReadWriteLock();public void readData() {rwLock.readLock().lock();try {// 读取操作} finally {rwLock.readLock().unlock();}
}public void writeData() {rwLock.writeLock().lock();try {// 写入操作} finally {rwLock.writeLock().unlock();}
}
场景
-
缓存系统:如热点数据缓存
-
配置中心:频繁读取,偶尔更新配置
四、乐观锁:StampedLock(JDK8+)
特性
-
乐观读锁
-
锁升级机制
StampedLock stampedLock = new StampedLock();// 乐观读
public double read() {long stamp = stampedLock.tryOptimisticRead();// 读取数据...if (!stampedLock.validate(stamp)) {stamp = stampedLock.readLock(); // 升级为悲观锁try {// 重新读取} finally {stampedLock.unlockRead(stamp);}}return data;
}// 写锁
public void write() {long stamp = stampedLock.writeLock();try {// 写操作} finally {stampedLock.unlockWrite(stamp);}
}
场景
-
高并发读:如股票行情系统
-
数据校验:先快速读取后验证
五、分布式锁
实现方式
-
Redis(RedLock算法)
-
ZooKeeper(临时有序节点)
-
数据库(唯一约束)
// Redis分布式锁示例(Jedis)
public boolean tryLock(String key, String value, int expire) {return "OK".equals(jedis.set(key, value, "NX", "EX", expire));
}public void unlock(String key, String value) {if (value.equals(jedis.get(key))) {jedis.del(key);}
}
场景
-
分布式系统:集群服务定时任务
-
资源抢占:如秒杀系统库存扣减
六、锁优化实践
-
减小锁粒度:ConcurrentHashMap分段锁
-
无锁编程:Atomic原子类
-
避免死锁:按顺序获取锁
-
锁分离:读写锁分离
总结对比
锁类型 | 特性 | 适用场景 |
---|---|---|
synchronized | 自动释放,非中断 | 简单同步 |
ReentrantLock | 灵活控制,可中断 | 复杂同步逻辑 |
ReadWriteLock | 读写分离 | 读多写少 |
StampedLock | 乐观读,高性能 | 高并发读 |
分布式锁 | 跨JVM | 分布式系统 |
选择合适的锁能显著提升系统性能。理解各锁的特性及适用场景,是构建高并发系统的关键技能。在实际开发中,建议先用synchronized,当需要更细粒度控制时再考虑显式锁。