簡體   English   中英

這些Java線程是否在等待獲得的鎖?

[英]Are these java threads waiting on the lock it acquires?

我正在查看一個jstack日志,這是我所看到的:

“ com.mchange.v2.async.ThreadPoolAsynchronousRunner $ PoolThread-#2”#250守護程序prio = 5 os_prio = 0 tid = 0x00007f9de0016000 nid = 0x7e54可運行[0x00007f9d6495a000] java.lang.Thread.State:在com.mchange.v 2可運行.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.java :534)-鎖定< 0x00000006fa818a38 >(com.mchange.v2.async.ThreadPoolAsynchronousRunner)

“ com.mchange.v2.async.ThreadPoolAsynchronousRunner $ PoolThread-#0”#248守護程序prio = 5 os_prio = 0 tid = 0x00007f9de001a000 nid = 0x7e52等待監視​​器條目[0x00007f9d64a5c000] java.lang.Thread.State:BLOCKED(在對象上監視器)在java.lang.Object.wait(本機方法)-在< 0x00000006fa818a38 >(com.mchange.v2.async.ThreadPoolAsynchronousRunner)上等待com.mchange.v2.async.ThreadPoolAsynchronousRunner $ PoolThread.run(ThreadPoolAsynchronousRunner.java :534)-鎖定< 0x00000006fa818a38 >(com.mchange.v2.async.ThreadPoolAsynchronousRunner)

因此,在此日志中,這三個線程中的每個線程都設法獲得了相同的鎖,並且實際上阻塞了底部的兩個線程,以等待相同的鎖。

有人可以告訴我這個堆棧日志是什么意思嗎?

最后兩個線程正等待通過將ThreadPoolAsynchronousRunner實例用作監視器來通知,因此該消息的來源將如下所示:

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

一旦調用waitasyncRunner上的同步asyncRunner被“釋放”,即應用程序的其他部分可以輸入在該實例上同步的塊。 在您的特定情況下,這似乎已經發生,並且第一個線程的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();
    }
}

如果添加了要處理的新消息,則ThreadPoolAsynchronousRunner``將啟動PoolThreads並執行notifyAll

// 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
    }
}

notifyAll會導致所有wait的所有線程的-方法返回,所以你必須檢查是否在父隊列中仍然包含數據(有時wait的回報,即使沒有通知發生,所以你需要此項檢查,即使不使用notifyAll )。 如果是這種情況,請啟動處理方法。 你應該做的是,外synchronized -塊,否則你的異步處理類只在時間處理一個消息(除非,這就是你想要的東西-但為什么運行多個PoolThread -instances?)

我能看到和理解的是

線程#2處於可運行狀態,並已獲得對象上的鎖

“ com.mchange.v2.async.ThreadPoolAsynchronousRunner $ PoolThread-#2” java.lang.Thread.State:RUNNABLE

線程#1線程#0正在等待該對象鎖被釋放並因此立即被阻塞。

“ com.mchange.v2.async.ThreadPoolAsynchronousRunner $ PoolThread-#1”“ com.mchange.v2.async.ThreadPoolAsynchronousRunner $ PoolThread-#0” java.lang.Thread.State:在java.lang上處於阻塞狀態(在對象監視器上) .Object.wait(本機方法)-等待<0x00000006fa818a38>

只有線程#2設法成功獲得對象鎖定,並且它處於RUNNABLE狀態。 其他2個線程(即Thread-#0Thread-#1)正在等待Thread-#2釋放該鎖。 只要Thread-#2保持鎖定, Thread-#0Thread-#1將保持鎖定狀態,並處於BLOCKED狀態。

如果您有權訪問源代碼,則可以查看該代碼,以確保是否以正確的順序進行了鎖定和解鎖,並且僅在必要時才對部分代碼進行了鎖定。 請記住,這兩個線程不是處於WAIT狀態,而是處於BLOCKED狀態,這是WAIT狀態之后的一個步驟,並且在鎖定可用后立即進入RUNNABLE狀態。

在此日志片段中未發現任何問題。 這還不是僵局。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM