Java ReentrantLock锁机制详解与可重入实现
自 Java 5 起,标准库提供了成熟的 ReentrantLock 等锁实现,替代了手写复杂的同步逻辑。本文将基于 Lock 接口特性,解析手动实现可重入锁的核心原理,展示临界区代码保护及异常处理的最佳实践。
结果与目标
掌握 java.util.concurrent.locks.Lock 的基本操作规范,理解如何实现具备可重入特性的线程锁,以及为何必须在异常环境下确保锁被释放。
准备条件
- JDK 环境(建议使用 JDK 8 及以上版本以获取完整的并发工具支持)。
- 对 Java 基础同步关键字
synchronized有基本了解。
真实操作顺序
第1步:使用 Lock 进行资源同步
目的:利用显式 Lock 对象替代同步块,实现对共享变量的安全访问。
入口:定义一个包含锁对象的类。
动作:在访问临界区前调用 lock(),结束后调用 unlock()。以下计数器示例展示了基本的加锁流程:
public class Counter {
private Lock lock = new ReentrantLock(); // 实际使用时推荐使用标准实现
private int count = 0;
public int inc() {
lock.lock();
try {
int newCount = ++count;
return newCount;
} finally {
lock.unlock(); // 推荐在finally中释放,防止遗漏
}
}
}
完成状态:在同一时刻只有一个线程能执行 ++count 操作,确保数据一致性。
第2步:解决锁的可重入性问题
目的:允许持有锁的线程再次进入由同一锁保护的临界区,避免自身死锁。
说明:synchronized 是可重入的,而简单的 Lock 模拟往往不可重入。若线程在进入 outer() 方法持有锁后,内部又调用同样需要该锁的 inner(),非重入锁会导致当前线程阻塞。
动作:修改锁的实现逻辑,记录当前持有锁的线程 ID 以及重入次数。
public class MyReentrantLock {
private boolean isLocked = false;
private Thread lockedBy = null; // 记录谁持有了锁
private int lockedCount = 0; // 记录重入次数
public synchronized void lock()
throws InterruptedException {
Thread callingThread = Thread.currentThread();
// 如果锁未被占用,或被同一个线程再次请求,则允许进入
while (isLocked && lockedBy != callingThread) {
wait();
}
isLocked = true;
lockedCount++;
lockedBy = callingThread;
}
public synchronized void unlock() {
if (Thread.currentThread() == this.lockedBy) {
lockedCount--;
if (lockedCount == 0) {
isLocked = false;
notify(); // 唤醒其他竞争锁的线程
}
}
}
}
完成状态:当 lockedCount 降为 0 时,才算真正释放锁,此时 notify() 才会被触发。
第3步:正确处理异常以防死锁
目的:保证临界区抛出异常时,锁依然能被释放,从而避免其他所有尝试获取该锁的线程永久阻塞。
动作:使用 try...finally 结构包裹业务逻辑。
lock.lock();
try {
// 执行可能抛出异常的临界区代码
} finally {
lock.unlock();
}
注意事项:切勿仅在正常路径下调用 unlock(),否则异常导致的未解锁将使整个系统处于停滞状态。
第4步:优化策略选择
目的:根据场景需求平衡性能与公平性。
说明:默认的 Lock 实现通常不保证公平性(即不一定按等待时间排序分配锁),这可能导致部分线程饥饿。synchronized 也不保证公平性。如需严格的等待顺序,可使用 new ReentrantLock(true)(开启公平模式),但这会牺牲一定的吞吐量。
简要总结
在 Java 高并发场景中,合理使用 Lock 接口及其扩展功能(如可重入、公平性、超时控制)比直接使用 synchronized 提供了更高的灵活性。关键在于理解临界区的边界管理以及异常流下的资源回收。以上就是关于 java 多线程-锁详解及示例代码的详细内容,更多关于 java 并发编程的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













