簡體   English   中英

多線程:應用程序每次都不會產生相同的結果

[英]Mutiple Threads: the application doesn't produce same result every time

因此,在這里我編寫了三個簡單的類來檢查多個線程在Java中的工作方式,但是每次運行它們都會產生不同的結果。 這是代碼:

        public class Accum {

        private static Accum a = new Accum();
        private int counter = 0;

        private Accum(){}

        public static Accum getAccum(){
            return a;
        }

        public void updateCounter(int add){
            counter+=add;
        }

        public int getCount(){
            return counter;
        }
    }//end of class

        public class ThreadOne implements Runnable {
        Accum a = Accum.getAccum();
        public void run() {
            for(int x=0; x<98; x++){
                //System.out.println("Counter in TWO "+a.getCount());
                a.updateCounter(1000);
                try{
                    Thread.sleep(50);
                }catch(InterruptedException ex){}
            }
            System.out.println("one " + a.getCount());
        }
    }//end of class

        public class ThreadTwo implements Runnable{
        Accum a = Accum.getAccum();
        public void run() {
            for(int x=0; x<99; x++){
                //System.out.println("counter in Two "+a.getCount());
                a.updateCounter(1);
                try{
                    Thread.sleep(50);
                }catch(InterruptedException ex){}
            }
            System.out.println("two "+a.getCount());
    }

        public class TestThreaad {
        public static void main(String[]args){
            ThreadOne t1 = new ThreadOne();
            ThreadTwo t2 = new ThreadTwo();

            Thread one = new Thread(t1);
            Thread two = new Thread(t2);

            one.start();
            two.start();
        }
    }end of class

因此,預期結果將是:一個98098,兩個98099,但事實證明結果是不可預測的,有時是78000或81000,我不知道。

但是,如果我添加一些代碼以打印當前計數值的一行,則最終結果將是正確的。

我真的不知道出了什么問題,甚至在ThreadOne和ThreadTwo的run()方法中添加了sync關鍵字,問題仍然存在。

我已經學習了3個月的Java,這是我所遇到的最難以捉摸的問題...所以在此先感謝任何人都可以幫助我了解多線程的基本知識...

代碼不同步。 由於未同步,因此嘗試更新計數器的其他Thread可能同時出現,從而導致此問題。

如果您同步化updateCounter ,則將可以正確訪問此方法。

public synchronized void updateCounter(int add){
      counter+=add;
}

在您的示例中, Accum實例在線程之間共享。 您的更新過程是典型的READ,COM​​PUTE-UPDATE,WRITE操作序列。 因為資源是共享的而不是受保護的,所以這三個操作(來自兩個線程-進行六個操作)可以以許多不同的方式交錯,從而導致更新丟失。

這是操作順序的示例(數字表示線程):

READ #1           -> reads 10
COMPUTE-UPDATE #1 -> computes 1010
READ #2           -> reads 10
WRITE #1          -> writes 1010
COMPUTE-UPDATE #2 -> computes 11
WRITE #2          -> writes 11 (earlier update is lost)

如此看來,幾乎任何結果都是可能的。 如@SubhrajyotiMajumder所述,您可以使用synchronized修復它。 但是,如果這樣做,線程可能不適合您的問題。 或者,您需要另一個算法過程。

您的代碼未正確同步。 作為同步方法的替代方法,我建議使用AtomicInteger存儲從不同線程訪問和修改的變量。

暫無
暫無

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

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