如何解决在另一个线程上获取 ReentrantReadWriteLock.ReadLock 时调用对象的同步方法
感谢您考虑我的问题,我认为这实际上是在问:
不太确定下面的代码究竟是如何死锁的。
结构大致如下,有2个类:
Worker 的 run
方法会死锁,使 doSomething()
不同步可以避免死锁。
真实应用的线程转储显示:
“Worker”线程被阻塞 - 等待监视器锁
--> 在 int v = Utils.getIntValue();
“计划”线程正在等待 - Thread State Details here
--> at (reentrantreadwritelock 的内部代码) after readWriteLock.readLock().lock();
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
的线程可以获取 ReadLock
内部 Worker,另一个 Worker 方法 reentrantreadwritelock
锁定在 Worker 对象上(内在锁),因此 2 个线程相互等待。
我可能完全错了,但如果目前没有错,我不确定 doSomething()
的这个实例如何知道引用它的 Worker 实例被另一个线程锁定?
似乎当预定的 reentrantreadwritelock
正在运行时,即使 Runnable task
方法返回后,Utils 类仍然被锁定?
更新scheduleTask
使用 0 秒延迟以更接近实际场景。
感谢您花时间考虑这个问题!
解决方法
事实证明,从 synchronized
线程调用了“Worker”的另一个 schedule
方法,并且有来自“Worker”超类的方法锁定在 ReentrantReadWriteLock.WriteLock()
...
“Worker”线程持有 WriteLock
并等待监视器锁
“schedule”线程持有 Worker 对象监视器锁并等待 ReadLock
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。