并发编程中的重入是指 允许线程多次获取同一个锁而不会造成死锁。当一个线程已经持有一个锁,并尝试再次获取该锁时,如果该锁支持重入,则该线程可以成功获取锁,而不会阻塞。重入机制通过为每个锁关联一个线程持有者和一个计数器来实现。计数器记录当前持有锁的线程数,当计数器为0时,表示锁未被任何线程持有,其他线程可以获取该锁。当线程释放锁时,计数器减1,当计数器回到0时,表示锁可以被其他线程获取。
重入锁与非重入锁的区别
非重入锁
多个线程访问同一个已经被加锁的方法时,一个线程拿到锁后,其他线程需要等待,直到锁被释放。
非重入锁在嵌套使用时容易引发死锁。
重入锁
允许同一个线程多次获取同一个锁,不会阻塞。
通过计数器记录锁的持有情况,确保线程安全地获取和释放锁。
重入锁的应用场景
重入锁在多线程编程中非常有用,特别是在以下场景:
当一个线程在持有锁的情况下调用其他需要锁保护的方法时。
当一个方法内部需要调用自身时(递归调用)。
在复杂的嵌套锁场景中,重入锁可以避免死锁的发生。
示例代码
```java
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
public void doSomething() {
lock.lock();
try {
// 执行需要锁保护的操作
System.out.println("Thread " + Thread.currentThread().getName() + " is doing something.");
// 递归调用自身
doSomething();
} finally {
// 释放锁
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockExample example = new ReentrantLockExample();
// 创建多个线程并发执行
for (int i = 0; i < 5; i++) {
new Thread(example::doSomething, "Thread-" + i).start();
}
}
}
```
在这个示例中,`ReentrantLock`确保了`doSomething`方法在并发执行时,每次只有一个线程能够获取锁并执行,从而避免了竞态条件。
总结
理解并发编程中的重入机制对于编写安全的多线程代码至关重要。通过使用重入锁,可以确保线程在获取和释放锁时的安全性和可靠性,避免死锁和其他并发问题。