2

同期メソッドと非同期メソッドの違いを設定しようとしています..次のコードを試しました

 class Counter {
    private int counter = 10;
    public int getCounter() {
        return counter;
    }

    public synchronized void doIncrementAndDecrement() {
        counter++;
        keepBusy(500);
        counter--;
    }

    public void keepBusy(int howLong) { // (D)
        long curr = System.currentTimeMillis();
        while (System.currentTimeMillis() < curr + howLong)
            ;
    }
}

class MyCounterThread extends Thread {

    Counter c;

    public MyCounterThread(Counter c, String name) {
        // TODO Auto-generated constructor stub
        super(name);
        this.c = c;
        start();
    }

    @Override
    public void run() {
        for (;;) {
            c.doIncrementAndDecrement();
            sleepForSometime();
            System.out.println(c.getCounter());
        }
    }

    public void sleepForSometime() { // (D)
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class UnSynchronizedExapmle {

    public static void main(String[] args) throws InterruptedException {
        Counter c = new Counter();
        MyCounterThread t1 = new MyCounterThread(c, "A");
        MyCounterThread t2 = new MyCounterThread(c, "B");
        MyCounterThread t3 = new MyCounterThread(c, "C");
    }
}

上記のように、doIncrementAndDecrement()同期メソッドがあります。

したがって、カウンターの値は毎回10になるはずです。しかし、これは起こりません。出力は次のようになります

10
10
11
10
10
10
10
11
10
10
11
10
11
11
10
10
11
10
11
10
10
10
11
10
10
11
10

なぜこれが起こるのか助けてください..または、同期方法と非同期方法の違いを説明するためのブログ/記事

4

3 に答える 3

5

getCounter() メソッドが同期されていません。したがって、あるスレッドがメソッドをロックしていても、別のスレッドがカウンター変数にアクセスして出力することができます

于 2012-05-17T07:26:28.333 に答える
2

System.out.printlnがカウンターの内部状態を出力する可能性があるため、コードはgetCounterメソッドを同期しません。synchronized on メソッドはsynchronized(this)と同じです。

于 2012-05-17T07:27:31.033 に答える
1

... keepBusy() メソッドに Thread.sleep() を記述すると、どのような違いが生じるのでしょうか..両方の場合で出力が大きく異なるためです。

それがすることkeepBusy()は、長い時間を要することgetCounter()です。

出力の違いはgetCounter()、インクリメントされた状態でカウンターを「見る」ことを防ぐ同期によるものです。

つまり、Thread.sleep() と上記の keepBusy() メソッドの while ループの違いは、スレッドのスケジューリングまたはロックに関して何を意味するのでしょうか。

違いはありません。


keepBusy()記録のために、実際のプログラムが、同期されたメソッドまたはブロックでスリープするようなメソッドを持つことは悪い考えです。これsleepにより、ターゲットオブジェクトで同期しようとしている他のスレッドがブロックされます...そして、アプリケーションの実際の並列性が低下する可能性があります。

于 2012-05-17T08:09:01.293 に答える