同步代码块 锁的处理

private final Object workbookLock = new Object();  
  
private int printImageXSSF(int length, XSSFWorkbook wb, XSSFSheet sheet, String imgPath) {  
    synchronized (workbookLock) {  
        // 你的代码逻辑  
    }  
    return length;  
}
private void insertImage(XSSFWorkbook wb, XSSFSheet sheet, ...) {  
    synchronized (workbookLock) {  
        try {  
            // 插入图片的代码  
        } finally {  
            // 这里不需要显式释放锁,因为 synchronized 块会自动处理  
        }  
    }  
}
ReentrantLock 是 Java 并发包 java.util.concurrent.locks 中的一个类,它实现了 Lock 接口,提供了一种比 synchronized 方法和语句更灵活的锁定机制。ReentrantLock 提供了多种功能,包括尝试非阻塞地获取锁、可中断地获取锁、尝试获取锁时设置超时时间等。

以下是如何使用 ReentrantLock 来处理对共享资源的同步访问的基本步骤:

1. 创建 ReentrantLock 实例
首先,你需要在你的类中创建一个 ReentrantLock 的实例。这个实例将用于控制对共享资源的访问。

java
private final ReentrantLock lock = new ReentrantLock();
2. 使用 lock() 方法获取锁
在访问共享资源之前,你需要调用 lock() 方法来获取锁。如果锁当前被其他线程持有,则当前线程将被阻塞,直到锁被释放。

java
lock.lock();  
try {  
    // 访问或修改共享资源的代码  
} finally {  
    // 释放锁  
    lock.unlock();  
}
3. 释放锁
在访问完共享资源后,你必须在 finally 块中调用 unlock() 方法来释放锁。这是非常重要的,以确保即使在发生异常时锁也能被正确释放。

4. 尝试非阻塞地获取锁
ReentrantLock 还提供了 tryLock() 方法,它尝试获取锁,但如果锁不可用,则不会阻塞当前线程,而是立即返回 false。

java
if (lock.tryLock()) {  
    try {  
        // 访问或修改共享资源的代码  
    } finally {  
        lock.unlock();  
    }  
} else {  
    // 无法获取锁时的处理逻辑  
}
5. 可中断地获取锁
ReentrantLock 还提供了 lockInterruptibly() 方法,它允许在等待锁的过程中被中断。如果当前线程在等待锁的过程中被中断,则会抛出 InterruptedException。

java
try {  
    lock.lockInterruptibly();  
    try {  
        // 访问或修改共享资源的代码  
    } finally {  
        lock.unlock();  
    }  
} catch (InterruptedException e) {  
    // 处理中断逻辑  
    Thread.currentThread().interrupt(); // 保留中断状态  
}
6. 尝试获取锁时设置超时时间
ReentrantLock 还提供了 tryLock(long timeout, TimeUnit unit) 方法,它尝试在给定时间内获取锁。如果在这段时间内成功获取了锁,则返回 true;如果在指定时间内没有获取到锁,则返回 false。

java
if (lock.tryLock(10, TimeUnit.SECONDS)) {  
    try {  
        // 访问或修改共享资源的代码  
    } finally {  
        lock.unlock();  
    }  
} else {  
    // 无法在指定时间内获取锁时的处理逻辑  
}
注意事项
确保在 finally 块中释放锁,以避免死锁。
ReentrantLock 是可重入的,即同一个线程可以多次获取同一个锁。但是,每次获取锁后都必须释放相应次数的锁。
使用 ReentrantLock 时,可以考虑使用条件变量(Condition),它提供了比 Object 监视器方法更灵活的线程间通信方式。

 

posted @ 2024-09-05 10:35  喜欢22度的晴天  阅读(4)  评论(0编辑  收藏  举报