感谢您考虑我的问题,我认为这实际上是在问:
不太确定下面的代码到底是如何死锁的。
结构大致如下所示,有2 个类:
- 主类 -具有同步方法的Worker
- 具有类级同步方法的util 类
Worker的run
方法会死锁,doSomething()
不同步可以避免死锁。
实际应用程序的线程转储显示:
“Worker”线程被阻塞-等待监视器锁定
-> int v = Utils.getIntValue();
“计划”线程正在等待 -此处的线程状态详细信息
--> 在 readWriteLock.readLock().lock() 之后的(ReentrantReadWriteLock 的内部代码);
at jdk.internal.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:194)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:885)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireShared(AbstractQueuedSynchronizer.java:1009)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1324)
public class Worker {
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public String getData() {
try{
readWriteLock.readLock().lock();
return "Data";
} finally {
readWriteLock.readLock().unlock();
}
}
public synchronized void doSomething() {
// blocked due to the invocation of Utils.scheduleTask
int v = Utils.getIntValue();
System.out.println(v);
}
public void run() {
// A static method which creates a thread that accesses the ReadWriteLock
Utils.scheduleTask(this::getData);
// some other quick tasks in between
// ...
// then enter this synchronized method
doSomething();
}
}
public class Utils {
static synchronized void scheduleTask(Runnable task) {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, r -> {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setName("schedule");
return t;
});
executorService.schedule(task, 0L, TimeUnit.SECONDS);
}
static int getIntValue() {
return 123;
}
}
我认为这是由于静态同步方法scheduleTask
锁定了整个Utils
类,然后在线程ExecutorService
可以获取内部 WorkerReadLock
之前,另一种 Worker 方法锁定在 Worker 对象(内在锁)上,因此 2 个线程正在等待对方。ReentrantReadWriteLock
doSomething()
我可能完全错了,但如果到目前为止没有错,我不确定这个实例是如何ReentrantReadWriteLock
知道引用它的 Worker 实例被另一个线程锁定的?
似乎当计划Runnable task
运行时,即使scheduleTask
方法返回,Utils 类仍然被锁定?
更新了scheduleTask
使用 0 秒延迟以更接近实际情况。
感谢您花时间考虑这个问题!