1. Java并发编程中的锁机制概述
在Java开发中,锁是保障线程安全的核心机制。想象一下银行转账的场景:如果没有锁机制,两个人同时向同一个账户转账,可能会导致余额计算错误。这就是为什么我们需要锁——它确保同一时间只有一个线程能访问共享资源。
Java的锁机制经历了多次演进:
- JDK 1.0:只有基本的synchronized
- JDK 1.5:引入更灵活的ReentrantLock
- JDK 1.8:新增高性能的StampedLock
- 分布式系统:Redis/ZooKeeper分布式锁
关键点:锁不是越高级越好,而是要根据具体场景选择最合适的方案。就像选择交通工具,短途骑自行车更灵活,长途则开车更合适。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. synchronized内置锁深度解析
2.1 基本用法与原理
synchronized是JVM级别的内置锁,它的实现基于对象头中的Mark Word。当线程进入synchronized代码块时:
- 尝试获取对象的monitor
- 成功则执行代码
- 失败则进入阻塞队列等待
java复制// 对象锁示例
public class Counter {
private int count;
private final Object lock = new Object();
public void increment() {
synchronized(lock) { // 锁定特定对象
count++;
}
}
}
2.2 类锁与对象锁的区别
很多初学者容易混淆这两种锁:
- 对象锁:锁定的是实例对象(this)
- 类锁:锁定的是Class对象(静态方法或Class对象)
java复制class LockExample {
// 类锁
public static synchronized void classLock() {
// 锁定的是LockExample.class
}
// 对象锁
public synchronized void instanceLock() {
// 锁定的是this实例
}
}
2.3 锁升级过程(偏向锁→轻量级锁→重量级锁)
现代JVM采用锁升级策略优化性能:
- 初始状态:无锁
- 第一个线程访问:偏向锁(记录线程ID)
- 出现竞争:升级为轻量级锁(CAS自旋)
- 自旋超过阈值:升级为重量级锁(操作系统互斥量)
实测数据:在低竞争场景下,偏向锁可以减少90%以上的同步开销。
3. ReentrantLock显式锁详解
3.1 核心特性对比
与synchronized相比,ReentrantLock提供了更多高级功能:
| 特性 | synchronized | ReentrantLock |
|---|---|---|
| 公平锁 | 不支持 | 支持 |
| 尝试获取锁 | 不支持 | tryLock() |
| 可中断 | 不支持 | lockInterruptibly() |
| 超时获取 | 不支持 | tryLock(timeout) |
| 条件变量 | 有限支持 | 多Condition支持 |
3.2 公平锁与非公平锁实战
公平锁按请求顺序分配,非公平锁允许插队:
java复制// 创建公平锁
ReentrantLock fairLock = new ReentrantLock(true);
// 创建非公
