簡體   English   中英

Java線程/ volatile

[英]Java threading/volatile

我有一個帖子:

class Foo extends Thread
{
    boolean active = true;

    public void run()
    {
        while(active)
        {
            //do stuff
        }
    }

    public void end()
    {
        active = false;
    }

    public void hibernate()
    {
        synchronized(this)
        {
            wait();
        }
    }
 }

如果另一個線程調用end()Foo立即看到active是否為false 具體來說,因為active不易volatile ,我不確定它會不會。 我最初創建end()作為一種避免volatile的聰明方法,但現在我不確定它實際上會做我想做的事情。 另外,如果另一個線程調用hibernate() ,哪個線程會進入休眠狀態? 我打算讓Foo睡覺,所以如果這不符合我的意圖,那么另一個建議將非常受歡迎。

如果另一個線程調用end(),Foo會立即看到active是否為false?

不,不會。 或者至少,它不會一直看到它。

如果你想讓run總是立即看到新值,那么在分配給變量的線程和讀取它的線程之間必須存在“后來”關系。 這可以實現:

  • 通過宣布active揮發性,
  • 通過在讀取和寫入變量的語句周圍放置synchronized塊,
  • 通過使變量成為“原子”類型; 例如AtomicBoolean ,或
  • 通過使用一些其他適當的並發類; 請參閱java.util.concurrent.*包。

......一種避免不穩定的聰明方法......

將變量聲明為volatile是確保正確同步的一種方法。 事實上,正確的同步會帶來性能開銷。 但是,正確的同步對於您的應用程序可靠地工作至關重要,並且避免它並不“聰明”。

(如果沒有適當的同步,你的程序可能仍然可以在大多數時間工作,它甚至可能總是在某些機器上工作。但是,偶爾它將無法工作,實際行為可能取決於你運行程序的機器在什么,機器負載是什么,以及其他東西。)

另外,如果另一個線程調用hibernate(),哪個線程會進入休眠狀態?

進行調用的線程將進入休眠狀態。 除非某個其他線程在同一個Foo對象上執行notifynotifyAll ,否則它不會被喚醒。

如果您只是希望應用程序進入休眠狀態並稍后喚醒,請使用Thread.sleep 但請注意,以錯誤的方式使用sleep會使您的應用程序變得緩慢且無響應。

你的懷疑是正確的:因為active不是volatile ,所以不能保證run()會看到在另一個線程上做出的更改。

一般來說,避免volatile “聰明”方法幾乎總是一個壞主意。 事實上,即使是volatile也是你不應該訴諸的東西。 大多數情況下,堅持使用鎖,監視器或更高級別的同步機制更安全。

對於第二個問題,將要進入休眠狀態的線程是調用hibernate()的線程。 該線程將一直睡眠,直到它被中斷,它會經歷虛假的喚醒,或者其他一些線程在Foo實例的監視器上調用notify() / notifyAll() 調用Object#wait()而不用一個檢查等待條件的循環來調用它通常是錯誤的。

你似乎也對 Foo實例“入睡”的想法感到困惑。 Foo實例不是 Thread (甚至是 Runnable ),並且不會創建自己的線程,因此它進入睡眠的想法並沒有多大意義。 您可能嘗試實現的是將調用 Foo#run()的線程置於休眠狀態。

關於避免volatile的第一個問題,您應該嘗試使用Thread中斷來指示正在運行的線程停止。

使用另一個線程的interrupt()實例方法來中斷正在運行的線程。

在正在運行的線程中使用isInterrupted()方法來檢查中斷。

while(!this.isInterrupted()){
   //do your work here.
}

不確定為什么要擴展Thread類。 如果在這種情況下實現Runnable,則應在run方法中使用interrupt來檢查中斷。 請閱讀javadocs以了解此方法的一些注意事項。

暫無
暫無

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

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