簡體   English   中英

Java線程處理:在lock.wait()中提供超時參數時發生意外行為

[英]Java Threading: Unexpected behavior when providing timeout argument in lock.wait()

不幸的是,由於周圍的代碼過於復雜,因此我無法提供完整的上下文信息。 簡短的是:

我有一段等待鎖的代碼:

            synchronized (lock) {
                lock.wait();
            }

哪個按預期工作。 非常簡單-它獲取鎖,在等待開始時釋放它,另一個線程獲取鎖,然后通知它。

但是,一旦提供超時,行為就會完全改變。

            synchronized (lock) {
                lock.wait(60000L);
            }

同樣,它應該非常簡單(這可以在代碼的其他幾個地方按預期工作)。 但是,在這種情況下,執行基本上會暫停,直到發生超時為止。 關於發生的事情,我的唯一猜測是進入等待狀態時不會釋放鎖-通知程序永遠無法獲取鎖,因此等待會一直休眠直到超時。 更糟糕的是,這是一個阻塞性的睡眠-沒有其他線程能夠等待鎖,這將強制執行完全同步。

有人對這里可能發生的事情有任何想法嗎? 這是一個相當簡單的功能,嵌套同步塊在任何時候都沒有發生任何奇怪的事情。 考慮到不提供任何超時,它應該無限期地等待,如果通知程序本身被破壞,代碼將永遠掛起,但事實並非如此。 只有在提供超時后,它才會停止工作。

任何想法將不勝感激。

作業系統:OS X 10.8.5

JDK:1.6.0、1.7.0.45和1.7.0.67

您的示例未顯示在wait()調用周圍的while()循環。 這表明您可能不完全了解等待和通知的用例。 這是一個例子:

// This object is used to synchronize *EVERY* method
// that can change the value of count.
final Object lock = new Object();

int count;

void waiter() {
    synchronized(lock) {
        while(count <= 0) {
            lock.wait();
        }
        //do something that you are only allowed to do
        //when count > 0.
    }
}

void notifier() {
    synchronized(lock) {
        count++;
        if (count >= 0) {
            lock.notify();
        }
    }
}

[編輯:添加了這一段,感謝內森·休斯(Nathan Hughes)提醒我...]調用循環處於循環中,因為在通知了鎖之后,wait()ing線程仍必須重新獲取該鎖:線程A等待條件變為真,線程B使條件變為真並調用notify(); 不能保證線程C不會首先獲得該鎖,並且在wait()調用能夠返回之前再次使條件變為假。

同樣,即使沒有通知對象,也允許wait()返回(這稱為“虛假喚醒”)。

在代碼中明確要等待的條件(即count> 0)。

除了在用於wait()和notify()調用的同一鎖對象上同步時,什么都沒有改變要等待的條件。

不管您是否提供超時,對象上的wait方法都將釋放當前線程在對象上持有的鎖(如John所評論)。

使用您提供的代碼並基於對場景的描述,我想是在執行lock.wait(60000L)的那一刻,JVM釋放了對象上的鎖,同時可能拾取處於運行/運行狀態的任何其他線程如果它們在同一個對象上進行同步,則它們可能在通知程序線程獲得該鎖定之前就獲得了鎖定。

此行為很難調試,因為它取決於JVM分析器來選擇應運行的線程。 因此,正如您在執行lock.wait(60000L)時所解釋的那樣,不必總是使通知程序線程單獨承擔對公共對象的鎖定。 如果還有其他線程也在公共對象上等待,那么它很可能最終獲得鎖定,從而導致通知程序線程無法獲得鎖定,因此lock.wait(60000L)超時。

每當使用lock.wait(..)時 ,都必須使用lock.notify()lock.notifyAll() 確保使用在邏輯上有意義的位置,並且它將在超時之前 “喚醒”鎖(考慮您放置的超時值就足夠了)。 這里是有關其用法的一些指南,我希望它有用: http : //www.javamex.com/tutorials/wait_notify_how_to.shtml

暫無
暫無

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

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