簡體   English   中英

使用偵聽器的怪異Java並發問題

[英]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.

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