### Java中的可重入锁(ReentrantLock)技术详解

75 阅读2分钟

在Java并发编程中,锁是保证数据在多线程环境下一致性和安全性的重要机制。Java标准库提供了多种锁的实现,其中ReentrantLock是可重入锁的一个典型实现,它属于java.util.concurrent.locks包。相比于内置的synchronized关键字,ReentrantLock提供了更灵活和强大的功能。

1. 可重入锁的概念

可重入锁(ReentrantLock)允许同一线程多次获取同一把锁,而不会造成死锁。这种特性使得锁在同一线程内可以被递归使用,从而避免了在递归调用时可能出现的死锁问题。

2. ReentrantLock的基本使用

使用ReentrantLock的基本步骤如下:

  1. 创建一个ReentrantLock对象。
  2. 在需要加锁的代码块前调用lock()方法获取锁。
  3. 在需要释放锁的代码块后调用unlock()方法释放锁。

示例代码:

java复制代码
	import java.util.concurrent.locks.ReentrantLock;  

	  

	public class ReentrantLockExample {  

	    private final ReentrantLock lock = new ReentrantLock();  

	  

	    public void someMethod() {  

	        lock.lock(); // 获取锁  

	        try {  

	            // 临界区,同一时间只有一个线程能执行这里的代码  

	            // ...  

	        } finally {  

	            lock.unlock(); // 释放锁  

	        }  

	    }  

	  

	    // 递归调用示例  

	    public void recursiveMethod() {  

	        lock.lock();  

	        try {  

	            // ...  

	            recursiveMethod(); // 递归调用自身,仍然可以获取锁  

	            // ...  

	        } finally {  

	            lock.unlock();  

	        }  

	    }  

	}

3. ReentrantLock的特性

  • 可重入性:同一个线程可以多次获取同一把锁,而不会被阻塞。
  • 公平锁与非公平锁ReentrantLock可以构造为公平锁或非公平锁。公平锁会按照线程请求锁的顺序来分配锁,而非公平锁则可能允许插队,即新请求的线程可能会立即获取锁,而等待时间较长的线程可能会继续等待。默认情况下,ReentrantLock是非公平锁。
  • 中断响应:与synchronized不同,ReentrantLock支持对等待锁的线程进行中断。
  • 尝试锁ReentrantLock提供了tryLock()方法,该方法会尝试获取锁,如果锁当前可用则获取锁并立即返回true,否则立即返回false
  • 定时锁ReentrantLock还提供了tryLock(long timeout, TimeUnit unit)方法,该方法会尝试获取锁,但如果在给定的等待时间内仍然没有获取到锁,则返回false

4. ReentrantLock与synchronized的比较

  • synchronized是Java内置的关键字,使用方便但功能有限;而ReentrantLock是Java标准库中的一个类,提供了更多的功能。
  • ReentrantLock支持公平锁和非公平锁,而synchronized只有非公平锁。
  • ReentrantLock支持对等待锁的线程进行中断,而synchronized不支持。
  • ReentrantLock提供了更灵活的锁控制,如尝试锁和定时锁,而synchronized不支持这些功能。

5. 总结

ReentrantLock作为Java中的一个可重入锁实现,提供了比synchronized更强大和灵活的功能。在需要更精细控制锁的行为时,使用ReentrantLock是一个很好的选择。然而,由于其使用相对复杂,需要确保在finally块中释放锁,以避免潜在的死锁问题。