[英]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對象上執行notify
或notifyAll
,否則它不會被喚醒。
如果您只是希望應用程序進入休眠狀態並稍后喚醒,請使用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.