本文目录导读:

我来为你展示几个可重入锁的经典案例,从基础到进阶逐步深入。
什么是可重入锁?
可重入锁(Reentrant Lock)指的是:同一个线程可以多次获取同一个锁而不会发生死锁。
public class ReentrantDemo {
public synchronized void methodA() {
System.out.println("进入方法A");
// 同一个线程可以再次获取锁
methodB(); // 不会死锁,因为synchronized是可重入的
}
public synchronized void methodB() {
System.out.println("进入方法B");
}
public static void main(String[] args) {
ReentrantDemo demo = new ReentrantDemo();
demo.methodA(); // 输出:进入方法A → 进入方法B
}
}
案例一:递归调用(最典型场景)
public class RecursiveLockDemo {
private int count = 0;
// 使用synchronized实现可重入
public synchronized void increment() {
count++;
System.out.println("当前值: " + count + ", 线程: " + Thread.currentThread().getName());
if (count < 5) {
increment(); // 递归调用,同一个线程再次进入
}
}
// 使用ReentrantLock实现可重入
private ReentrantLock lock = new ReentrantLock();
public void incrementWithLock() {
lock.lock();
try {
count++;
System.out.println("Lock值: " + count + ", 持有锁次数: " + lock.getHoldCount());
if (count < 3) {
incrementWithLock(); // 递归调用
}
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
RecursiveLockDemo demo = new RecursiveLockDemo();
demo.increment(); // 输出1-5,不会死锁
}
}
案例二:继承关系中的重入
public class InheritanceReentrantDemo {
static class Parent {
public synchronized void doSomething() {
System.out.println("父类方法执行 - " + Thread.currentThread().getName());
}
}
static class Child extends Parent {
@Override
public synchronized void doSomething() {
System.out.println("子类方法执行 - " + Thread.currentThread().getName());
// 调用父类方法,需要再次获取锁
super.doSomething(); // 这是可重入的,不会死锁
}
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
}
案例三:ReentrantLock的高级特性
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockAdvancedDemo {
// 公平锁:true表示公平锁
private ReentrantLock fairLock = new ReentrantLock(true);
// 非公平锁:默认
private ReentrantLock nonFairLock = new ReentrantLock();
public void demonstrateFeatures() throws InterruptedException {
// 1. 可重入性验证
fairLock.lock();
try {
System.out.println("第一次获取锁");
System.out.println("锁持有次数: " + fairLock.getHoldCount());
fairLock.lock(); // 再次获取
try {
System.out.println("第二次获取锁");
System.out.println("锁持有次数: " + fairLock.getHoldCount());
} finally {
fairLock.unlock();
System.out.println("释放一次,剩余持有次数: " + fairLock.getHoldCount());
}
} finally {
fairLock.unlock();
System.out.println("释放一次,剩余持有次数: " + fairLock.getHoldCount());
}
// 2. 可中断性
Thread waitingThread = new Thread(() -> {
try {
nonFairLock.lockInterruptibly();
try {
System.out.println("线程获取到锁");
} finally {
nonFairLock.unlock();
}
} catch (InterruptedException e) {
System.out.println("线程被中断,无法获取锁");
}
});
waitingThread.start();
Thread.sleep(100);
waitingThread.interrupt(); // 中断等待的线程
// 3. 尝试获取锁(非阻塞)
if (nonFairLock.tryLock()) {
try {
System.out.println("成功获取锁");
} finally {
nonFairLock.unlock();
}
} else {
System.out.println("锁被占用,操作失败");
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockAdvancedDemo demo = new ReentrantLockAdvancedDemo();
demo.demonstrateFeatures();
}
}
案例四:数据库连接池(实际应用)
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;
public class ConnectionPoolDemo {
private static class Connection {
private boolean inUse = false;
public void use() {
System.out.println("连接被使用 - " + Thread.currentThread().getName());
// 模拟耗时操作
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
private final Connection[] connections;
private final boolean[] used;
private final ReentrantLock lock = new ReentrantLock();
private final java.util.concurrent.locks.Condition available = lock.newCondition();
public ConnectionPoolDemo(int size) {
connections = new Connection[size];
used = new boolean[size];
for (int i = 0; i < size; i++) {
connections[i] = new Connection();
}
}
public Connection getConnection() throws InterruptedException {
lock.lock();
try {
while (true) {
// 查找空闲连接
for (int i = 0; i < connections.length; i++) {
if (!used[i]) {
used[i] = true;
System.out.println("获取连接 " + i + " - " + Thread.currentThread().getName());
return connections[i];
}
}
// 没有空闲连接,等待
System.out.println("等待连接... - " + Thread.currentThread().getName());
available.await(1, TimeUnit.SECONDS);
}
} finally {
lock.unlock();
}
}
public void returnConnection(Connection connection) {
lock.lock();
try {
for (int i = 0; i < connections.length; i++) {
if (connections[i] == connection && used[i]) {
used[i] = false;
System.out.println("归还连接 " + i + " - " + Thread.currentThread().getName());
available.signalAll();
return;
}
}
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ConnectionPoolDemo pool = new ConnectionPoolDemo(2);
// 模拟多个线程使用连接池
for (int i = 0; i < 4; i++) {
new Thread(() -> {
try {
Connection conn = pool.getConnection();
conn.use();
pool.returnConnection(conn);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "线程-" + i).start();
}
}
}
案例五:性能对比和注意事项
public class PerformanceComparisonDemo {
// 循环次数
private static final int LOOPS = 1000000;
// 使用synchronized
private int syncCount = 0;
// 使用ReentrantLock
private int lockCount = 0;
private final ReentrantLock lock = new ReentrantLock();
public synchronized void incrementSync() {
syncCount++;
}
public void incrementLock() {
lock.lock();
try {
lockCount++;
} finally {
lock.unlock();
}
}
public void comparePerformance() {
// 测试synchronized
long startTime = System.nanoTime();
for (int i = 0; i < LOOPS; i++) {
incrementSync();
}
long syncTime = System.nanoTime() - startTime;
// 测试ReentrantLock
long startTime2 = System.nanoTime();
for (int i = 0; i < LOOPS; i++) {
incrementLock();
}
long lockTime = System.nanoTime() - startTime2;
System.out.println("synchronized耗时: " + syncTime / 1000000 + "ms");
System.out.println("ReentrantLock耗时: " + lockTime / 1000000 + "ms");
}
public static void main(String[] args) {
PerformanceComparisonDemo demo = new PerformanceComparisonDemo();
demo.comparePerformance();
// 注意事项示例
System.out.println("\n=== 注意事项 ===");
System.out.println("1. 必须成对使用lock/unlock,用try-finally保证");
System.out.println("2. 不要忘了释放锁,否则会造成死锁");
System.out.println("3. 尽量使用锁的作用域最小化");
System.out.println("4. 考虑使用tryLock避免死锁");
}
}
常见问题解答
public class CommonQuestionsDemo {
// Q1: synchronized和ReentrantLock的区别?
public static void question1() {
System.out.println("=== 区别 ===");
System.out.println("1. synchronized是JVM层面,ReentrantLock是JDK层面");
System.out.println("2. ReentrantLock支持中断、超时、公平锁");
System.out.println("3. ReentrantLock需要手动释放锁");
System.out.println("4. synchronized会自动释放锁");
}
// Q2: 什么情况下会发生死锁?
public static void question2() {
Object lockA = new Object();
Object lockB = new Object();
// 死锁示例
Thread thread1 = new Thread(() -> {
synchronized (lockA) {
System.out.println("线程1持有锁A");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lockB) {
System.out.println("线程1持有锁B");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lockB) {
System.out.println("线程2持有锁B");
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized (lockA) {
System.out.println("线程2持有锁A");
}
}
});
System.out.println("=== 这会产生死锁,因为线程互相等待对方持有的锁 ===");
System.out.println("解决方式:\n1. 按顺序获取锁\n2. 使用tryLock设置超时\n3. 使用Lock-free数据结构");
}
public static void main(String[] args) {
question1();
System.out.println();
question2();
}
}
- 可重入锁的本质:同一线程可以多次获取同一个锁,通过计数器记录持有次数
- 两种实现方式:
synchronized关键字和ReentrantLock类 - 主要应用场景:递归调用、方法嵌套、继承中的锁传递
- ReentrantLock优势:提供更多特性(可中断、可超时、公平锁等)
- 使用注意事项:必须成对使用lock/unlock,确保释放锁
这些案例涵盖了可重入锁的主要使用场景,从简单的递归到实际的项目应用,希望能帮助你深入理解可重入锁的机制和用法。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播