1

したがって、ここでは、Java で複数のスレッドがどのように動作するかを検査する 3 つの単純なクラスを作成しますが、実行するたびに異なる結果が生成されます。コードは次のとおりです。

        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 が 1 つ、98099 が 2 つですが、結果は予測不可能であることがわかります。78000 または 81000 になることもあります。わかりません..

しかし、カウントの現在の値の行を出力するコードを追加すると、最終結果は正しいでしょう..

何が問題なのか本当にわかりません.ThreadOneとThreadTwoのrun()メソッドで同期されたキーワードを追加しても、問題はまだあります...

私は3か月間Javaを研究してきましたが、これは私が今まで直面した中で最もとらえどころのない問題です...マルチスレッドの基本的なポイントを理解するのに役立つ人がいることに感謝します...

4

3 に答える 3

2

コードが同期されていません。同期されていないため、異なるThreadカウンターを更新しようとすると、同時にこの問題が発生する可能性があります。

同期した場合updateCounter、このメソッドのアクセスは適切になります。

public synchronized void updateCounter(int add){
      counter+=add;
}
于 2013-09-02T11:26:13.623 に答える
1

あなたの例では、Accumインスタンスはスレッド間で共有されています。更新プロセスは、典型的な READ、COMPUTE-UPDATE、WRITE 操作シーケンスです。リソースは共有され、保護されていないため、(2 つのスレッドからの 6 つの操作を行う) これら 3 つの操作がさまざまな方法でインターリーブされ、更新が失われる可能性があります。

操作の順序の例を次に示します (番号はスレッドを示します)。

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それを修正するために使用できます。しかし、それを行うと、スレッドが問題に適していない可能性があります。または、別のアルゴリズム プロセスが必要です。

于 2013-09-02T11:35:24.617 に答える
0

コードが正しく同期されていません。同期メソッドの代わりに、AtomicInteger異なるスレッドからアクセスおよび変更された変数を格納するために使用することをお勧めします。

于 2013-09-02T11:37:53.620 に答える