java - 在另一个线程上获取 ReentrantReadWriteLock.ReadLock 时调用对象的同步方法
问题描述
感谢您考虑我的问题,我认为这实际上是在问:
不太确定下面的代码到底是如何死锁的。
结构大致如下所示,有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 秒延迟以更接近实际情况。
感谢您花时间考虑这个问题!
解决方案
事实证明,线程synchronized
调用了另一种“Worker”方法,并且“Worker”的schedule
超类中的方法被锁定在ReentrantReadWriteLock.WriteLock()
...
“Worker”线程持有WriteLock
并等待监视器锁
“schedule”线程持有 Worker 对象监视器锁并等待ReadLock
推荐阅读
- python - 因此,既然 Scapy 已重命名为 Kamene,我将如何导入和使用 base64_bytes?
- php - 数组中文件的内容并将其分解
- docker - 使用 docker-compose 在容器之间共享 IP
- regex - sed 正则表达式:组重复选项?
- c++ - C++ 可变数量的可变参数模板参数
- r - 按向量计算矩阵运算分组的有效策略
- vue.js - 如何使用 vuex 控制数组状态?
- php - RegEx:不包括特定数字的数字范围
- python - 如何在对输入数据进行归一化后对神经网络预测进行反规范化?
- node.js - Cost, Performance and pitfall of Invalidating JWT