使用synchronized
- 处理思路:
synchronized
是基于JVM的内置锁。当一个线程获取到synchronized
锁进入临界区时,另一个线程发起中断请求,被中断线程在try - catch
块中捕获到中断异常InterruptedException
。在catch
块中,由于try
块内代码已经持有synchronized
锁,当执行完catch
块逻辑(例如记录日志、进行一些清理操作)后,线程退出try - catch
块,此时synchronized
锁会自动释放,从而确保锁的正确释放。同时,synchronized
保证了同一时刻只有一个线程能进入临界区,所以数据一致性在锁的作用下得以维持。
- 示例代码如下:
public class SynchronizedInterruptExample {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
Thread interruptingThread = new Thread(() -> {
try {
Thread.sleep(1000);
mainThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
interruptingThread.start();
synchronized (lock) {
try {
System.out.println("Main thread entered critical section");
while (!Thread.currentThread().isInterrupted()) {
// 模拟临界区操作
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted");
// 可以在这里进行一些清理操作
}
}
System.out.println("Main thread released lock");
}
}
- 可能遇到的问题:
- 如果在
catch
块中没有正确处理中断(例如忽略中断异常),线程可能不会正确响应中断,导致锁不能及时释放,影响系统的并发性能。
synchronized
锁是不可中断的,一旦线程获取到锁进入临界区,除非线程正常执行完临界区代码或者抛出未捕获的异常,否则其他线程无法中断它,这可能导致在某些需要及时响应中断的场景下出现问题。
使用ReentrantLock
- 处理思路:
ReentrantLock
提供了可中断的锁获取方式lockInterruptibly()
。当一个线程通过lockInterruptibly()
获取到锁并进入临界区时,另一个线程发起中断请求,被中断线程会在执行lockInterruptibly()
处或者在临界区内抛出InterruptedException
。在捕获到该异常后,线程可以在catch
块中调用unlock()
方法来手动释放锁,从而确保锁的正确释放。同时,ReentrantLock
通过独占锁的机制保证同一时刻只有一个线程能进入临界区,维持数据一致性。
- 示例代码如下:
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockInterruptExample {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
Thread interruptingThread = new Thread(() -> {
try {
Thread.sleep(1000);
mainThread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
interruptingThread.start();
try {
lock.lockInterruptibly();
System.out.println("Main thread entered critical section");
while (!Thread.currentThread().isInterrupted()) {
// 模拟临界区操作
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted");
// 释放锁
lock.unlock();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
System.out.println("Main thread released lock");
}
}
- 可能遇到的问题:
- 如果在
catch
块中忘记调用unlock()
方法释放锁,会导致锁永远不会被释放,其他线程无法获取锁,造成死锁。
- 由于
ReentrantLock
需要手动释放锁,在复杂的业务逻辑中,如果unlock()
调用的位置不正确(例如在异常处理中没有正确释放锁,或者在多个try - catch
块中有遗漏),也可能导致锁释放问题,影响数据一致性和系统并发性能。