[英]Weird java concurrency issue using a listener
我目前正在學習Java的並發性,我只是想知道Java偵聽器是否是線程安全的,所以我寫了這個。 我遇到了一個非常奇怪的問題,即如果將println注釋掉,該程序將永遠不會退出。 我應該在什么時候不同步一些東西嗎?
有任何想法嗎?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class MainComponent implements MainThreadListener
{
private static final int THREADS = 10;
int notifsOld;
int notifs;
public MainComponent()
{
notifs = 0;
notifsOld=0;
}
public void start()
{
dispatch();
loop();
}
public void dispatch()
{
/* start 10 threads
* the lewThread starts, sleeps for (0-10 secs)
* and then notifies the MainComponents implemented listener */
for (int i = 0; i <= THREADS; i++) {
new LewThread(this).start();
}
}
public void loop()
{
while(notifs < THREADS)
{
/* when println is commented out, the program will never end. ??? */
//System.out.println(notifs);
if(notifs != notifsOld)
{
/* this only runs once at the end */
notifsOld = notifs;
System.out.println("notifs changed");
}
}
}
@Override
public void threadNotified(){notifs++;}
public static void main(String... args)
{
new MainComponent().start();
}
}
只需嘗試同步您的threadNotified方法:
public synchronized void threadNotified(){notifs++;}
這將確保沒有2個線程將同時增加notifs
,這將導致一個增量。 您可能還應該同步所有對變量的訪問。
我認為一個更簡單的選擇是將notifs
變量標記為volatile:
volatile int notifsOld;
volatile int notifs;
通常,在Java中,每個線程都會獲得每個變量自己的本地副本。 易失性確保所有這些副本在被紅色或寫入之前都已同步。 因此,所有線程都作用於變量的相同值。
看來您已經遇到了經典的JIT語言“性能測試”問題。 JIT(Just In Time)編譯器將僅編譯具有可觀察輸出的代碼路徑。 當您注釋掉Println時,代碼不再執行任何操作,因此編譯器會優化整個代碼分支。
最有可能優化了整個代碼分支loop(),並且僅運行調度。 您可以嘗試在調試中使用eclipses“ step over”命令來查看它是否真正運行循環。 或者,嘗試將“ println(notifs +”“ + notifsOld”)放在loop()之后; 這將使通知更新再次變得重要。
另外,您應該使Notifs(原子的和易失的)或同步,但是我並不真正認為這是問題所在。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.