同步代码块 锁的处理
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 监视器方法更灵活的线程间通信方式。