Java新同步机制:可重入锁ReentrantLock详解

0 下载量 15 浏览量 更新于2024-09-01 收藏 51KB PDF 举报
"Java线程的新同步机制主要围绕可重入锁ReentrantLock展开,它类似于synchronized关键字,用于确保临界区的互斥访问。ReentrantLock提供了更灵活的控制,包括非阻塞的尝试锁定和明确的解锁操作。" 在Java中,线程同步是确保多线程环境下数据一致性的重要手段。传统的synchronized关键字虽然简单易用,但在某些场景下可能不够灵活。可重入锁ReentrantLock则弥补了这一不足,它允许程序员更加精细地管理锁的获取和释放。 1. 可重入锁ReentrantLock的接口与使用: - 创建ReentrantLock:通过`new ReentrantLock()`实例化。 - 请求锁:使用`lock()`方法,如果锁已被其他线程持有,当前线程会被阻塞。 - 释放锁:调用`unlock()`方法,必须确保在不再需要锁时释放它,防止死锁。 - 非阻塞式获取锁:`tryLock()`尝试获取锁,如果锁可用则立即返回true,否则返回false。 2. 基本使用模式: - 建议使用`try-finally`结构确保在任何情况下都能释放锁,即使在try块中有异常抛出。例如: ``` locker.lock(); try { // 临界区代码 } finally { locker.unlock(); } ``` 这种方式保证了在执行完临界区代码后,无论是否出现异常,都会释放锁。 3. 锁的可重入性: - ReentrantLock的一个关键特性是可重入性,即线程可以多次获取同一锁。这意味着一个线程在持有锁的情况下,可以再次请求该锁而不会被阻塞。内部的持有计数会跟踪每个线程对lock方法的嵌套调用。在解锁时,持有计数会递减,当计数归零时,锁才会真正释放。 4. 示例代码: ```java class WorkerOne extends Thread { private Lock locker; public WorkerOne(Lock locker) { this.locker = locker; } public void run() { locker.lock(); try { System.out.println(Thread.currentThread().getName() + ": step into critical section"); } finally { locker.unlock(); } } } class WorkerTwo extends Thread { private Lock locker; public WorkerTwo(Lock locker) { this.locker = locker; } public void sayHello() { // 同样使用相同的锁 } } ``` 在上述例子中,`WorkerOne`和`WorkerTwo`线程共享同一个`ReentrantLock`,它们在进入临界区前都需要获取锁。由于锁的可重入性,`WorkerOne`线程在临界区内可以安全地调用使用相同锁的方法,如`sayHello()`。 5. 其他特性: - `ReentrantLock`还支持公平锁(按照等待时间顺序获取锁)和非公平锁(不保证等待时间,线程可能直接获取锁),可以通过构造函数指定。 - 可以使用`tryLock(long time, TimeUnit unit)`尝试在指定时间内获取锁,如果超时未获取则返回false。 - 提供了`isLocked()`和`isHeldByCurrentThread()`方法来检查锁的状态。 - `Condition`接口允许创建条件变量,实现更复杂的同步控制。 通过ReentrantLock,Java开发者可以在需要时选择更高的控制级别,以适应更复杂多变的并发环境,同时保证线程安全和性能。