当前位置: 首页 > 知识库问答 >
问题:

在获取ReentrantReadWriteLock时调用对象的同步方法。另一个线程上的ReadLock

殷宾白
2023-03-14

谢谢你考虑我的问题,我认为这实际上是在问:

不太确定下面的代码会如何死锁。

其结构大致如下所示,有两个类:

    < li >具有同步方法的主类工作器 < li >具有类级别同步方法的util类

Worker的< code>run方法会死锁,使< code>doSomething()不同步可以避免死锁。

真实应用程序的线程转储显示:

“Worker”线程被阻塞-正在等待监视器锁定--

此处的“schedule”线程是WAITING-thread State Details--

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)
java prettyprint-override">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;
    }
}

我认为这是由于静态同步方法schduleTask锁定了整个Utils类,然后在ExecutorService的线程可以获得Worker内部的ReentantReadWriteLockReadLock,Worker的另一种方法doThings()锁定在Worker对象上(内在锁),因此2个线程正在相互等待。

我可能完全错了,但如果到目前为止没有错,我不确定这个的实例如何知道引用它的Worker实例被另一个线程锁定?

似乎当计划的< code>Runnable task正在运行时,即使< code>scheduleTask方法已经返回,Utils类仍然被锁定。

更新了scheduleTask以使用0秒延迟,更接近实际场景。

感谢您花时间考虑这个问题!

共有1个答案

姜博
2023-03-14

结果是,从< code>schedule线程调用了“Worker”的另一个< code>synchronized方法,并且在< code>ReentrantReadWriteLock上锁定了来自“Worker”超类的方法。WriteLock()...

“Worker”线程持有< code>WriteLock并等待监视器锁

“计划”线程持有Worker对象监视器锁并等待ReadLock

 类似资料:
  • 假设我们有两个类A、B和各自类的同步方法methodA、methodB。如果我们从synchronizedmethodA调用synchronized methodB,那么当methodB仍在执行时,线程是否仍对ObjectA保持锁定?

  • 我想在一个方法pointcut上编写一个方面,在该方面中,我想使用调用pointcut方法的对象调用另一个方法。 类似于这样: 我不确定我是否使方面的用法太复杂了,因为我在任何地方都找不到这样的用法。

  • 目前,我使用的是firebase实时数据库。因此,我的数据更改来自另一个线程。因此,我无法控制何时更新新的数据。然后我如何知道何时调用以刷新UI? 谢谢

  • 问题内容: 如果一个同步方法调用另一个同步方法,那么线程安全吗? 问题答案: 是的,将方法标记为时,您实际上是在这样做: 当线程调用从method1进入method2时,它将确保它持有对的锁定,该锁定已经存在,然后可以通过。 当线程直接进入method1或method2时,它将阻塞直到获得锁(),然后进入。 正如詹姆斯·布莱克(James Black)在评论中指出的那样,您必须了解方法主体内部的操

  • 我已经面临这个问题很多天了,请帮我解决。我正在使用线程同步实现生产者-消费者示例。我在这个传统节目中做了一些调整。我没有只使用一个队列对象,而是使用了两个队列对象。但程序不起作用。。(PS-我知道我可以通过只使用队列的一个对象来让这个程序工作,但如果我想使用两个队列对象呢??) 类队列{ } 类生产者实现Runnable{ } 类消费者实现可运行{ } 公共类测试队列{ }

  • 问题内容: 在Bruce Eckel的“ Thinking In Java,第四版”的第428页(有关类型信息的章节)中,具有以下示例: 也许我有点累,但是我看不到add()方法中对add()的调用是如何工作的。我一直认为它应该有一个引用,或者是一个静态方法(并且我在ArrayList或List中找不到静态add())。我想念什么? 我只是为自己测试,发现这可行: 问题答案: Java为这样的方法