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

这些java线程正在等待它获取的锁吗?

法池暝
2023-03-14

我正在查看一个jstack日志,下面是我看到的:

“com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2”#250 daemon prio=5 os_prio=0 tid=0x00007F9DE0016000 nid=0x7e54 runnable[0x00007F9D6495A000]java.lang.Thread.State:在com.mchange.v2.async.ThreadPoolAsynchronousRunner处可运行$PoolThread.Run(ThreadPoolAsynchronousRunner.java:534)-锁定<0x00000006FA818A38>(一个com.mchange.v2.async.ThreadPoolAsynchronousRunner)

“com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1”#249后台进程prio=5 OS_prio=0 tid=0x00007F9DE000C000 NID=0x7E53等待监视器条目[0x00007F9D649DB000]java.lang.Thread.State:在java.lang.object.wait(本机方法)-在<0x00000006FA818A38>(com.mchange.v2.async.ThreadPoolAsynchronousRunner)在com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner上等待OusRunner.java:534)-锁定<0x00000006FA818A38>(一个com.mchange.v2.async.ThreadPoolAsynchronousRunner)

“com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0”#248 daemon prio=5 os_prio=0 tid=0x00007F9DE001A000 nid=0x7e52等待监视器条目[0x00007F9D64A5C000]java.lang.Thread.state:在java.lang.object.wait(本机方法)-在<0x00000006FA818A38>(com.mchange.v2.async.ThreadPoolAsynchronousRunner)在com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynn)上被阻止(在对象监视器上)ChronousRunner.java:534)-锁定<0x00000006FA818A38>(一个com.mchange.v2.async.ThreadPoolAsynchronousRunner)

因此,在本日志中,这三个线程中的每一个线程都设法获得了相同的锁,而底部的两个线程实际上被阻塞了,等待相同的锁。

有人能给我解释一下这个堆栈日志是什么意思吗?

共有1个答案

於德馨
2023-03-14

最后两个线程正在等待通过使用ThreadPoolAsynchronousRunner的实例作为监视器得到通知,因此其来源如下所示:

synchronized(asyncRunner) {
    // ...
    asyncRunner.wait();
    // ...
}

只要调用waitAsyncrunner上的同步就会“释放”,即应用程序的其他部分可以进入在该实例上同步的块。在您的特定情况下,似乎已经发生了这种情况,第一个线程的wait-call返回,并且它当前正在处理来自它的一些数据。您仍然会在线程转储中看到多个locked行,以显示代码当前在synchronized块中,但如前所述,当调用wait时会释放“锁”。

您在这里看到的线程转储技术在将并发包添加到JDK以避免代价高昂的线程创建之前是非常常见的。您的线程转储类似于这种实现。下面是一个简单的实现,它看起来像是“在引擎盖下”:

// class ThreadPoolAsynchronousRunner
private Deque<AsyncMessage> queue;

public synchronized void addAsyncMessage(AsyncMessage msg) {
    queue.add(msg);
    notifyAll();
}

public void start() {
    for (int i = 0; i < 4; i++) {
        PoolThread pt = new PoolThread(this);
        pt.start();
    }
}
// PoolThread

public PoolThread(ThreadPoolAsynchronousRunner parent) {
    this.parent = parent;
}

public void run() {
    try {
        while (true) {
            AsyncMessage  msg = null;
            synchronized(parent) {
                parent.wait();
                if (!parent.queue.isEmpty()) {
                    msg = queue.removeFirst();
                }
            }
            if (msg != null) {
                processMsg(msg);
            }
        }
    }
    catch(InterruptedException ie) {
        // exit
    }
}
 类似资料:
  • 问题内容: 在Java线程转储中,您可以看到堆栈跟踪中提到的锁。 似乎有三种信息: 1: 2: 3: 1:线程已获得对象0x00002aab329f7fa0的锁。 2&3:似乎是说线程正在等待该对象上的锁可用… 但是2和3有什么区别? 问题答案: 使用内在锁时,您将在线程转储中获得“等待锁”,而使用java.util.concurrent中的锁时,将获得“停放以等待”。考虑以下示例: 随着您将获得

  • 问题内容: 我有以下情况: 为了运行算法,我必须运行多个线程,并且每个线程都会在死之前设置一个实例变量x。问题是这些线程不会立即返回: 我应该使用等待通知吗?还是我应该嵌入一个while循环并检查是否终止? 感谢大家! 问题答案: 创建一些共享存储来保存每个线程的值,或者如果足够的话,只存储总和。使用a 等待线程终止。每个线程完成后都会调用,您的方法将使用该方法来等待它们。 编辑: 这是我建议的方

  • 我做了几个线程转储,发现有16个线程在等待同一个锁,例如: “__ejb-thread-pool1”守护进程prio=6 tid=0x39657c00 nid=0x1c08在条件[0x3297f000]java.lang.thread.state:waiting(parking)在sun.misc.unsafe.park(本机方法)-在java.util.concurrent.locks.lock

  • 但这一个也不起作用。正确的答案是加入线程并删除2个睡眠: 我的问题是:为什么我的答案都不能被接受?我的实验室领导问,但他不能给我一个答案。在家里编写了测试代码,它似乎工作得很好。提前感谢您的帮助!

  • 从理论上讲,一个等待线程(假设Thread_1)首先获取一个互斥体,然后通过调用wait()等待条件变量。对wait()的调用会立即解锁互斥体。当另一个线程(比如Thread_2)调用notify()时,等待的线程(Thread_1)被唤醒,相同的互斥体在等待之前被锁定(..)调用返回。 现在假设多个线程在给定的时间等待一个条件变量(假设是Thread_1、Thread_2和Thread_3)。现

  • 嗨,我正在做一个项目,我已经达到了我非常困的部分。我试图寻找方法来学习如何在繁忙的等待中编写 while 循环,但我没有找到任何东西,我的代码只是作为无限循环运行。有人可以帮助我解释一个繁忙的等待循环应该如何工作,并帮助我打破这个无限循环吗? 该项目希望做到以下几点:早上,学生醒来后(这需要一段随机的时间),他会去洗手间为新的上学日做准备。如果浴室已经客满,学生需要Rest一下(使用yield()