0

私はスレッドに非常に慣れていません。私はコードを書き、出力が一貫して 20000 になることを期待していました。しかし、そうではありません。以下のコードを見つけてください。

class Runner4 implements Runnable {

    static int count = 0;

    public synchronized void increase() {
        count++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            increase();
        }
    }
}

public class threading4 {

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runner4());
        t1.start();
        Thread t2 = new Thread(new Runner4());
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(Runner4.count);
    }
}

説明はありますか?

ありがとう!!

4

3 に答える 3

1

コード内の 2 つの異なるオブジェクト (作成した 2 つのオブジェクトに対応) で同期しています。そのため、共有静的変数は保護されず、予測できない結果が得られます。基本的に、プログラムでは効果的な同期は行われません。これは簡単な変更で修正できます。

変化する:

public synchronized void increase(){
    count++;
}

に:

public void increase(){
    synchronized(Runner4.class) {
        count++;
    }
}

これがこの種の同期を実現する最良の方法であると言っているわけではありませんが、重要なことは、クラス レベルの変数を変更する場合は、クラス レベルの同期も必要であるということです。

于 2013-02-10T02:36:24.590 に答える
0

countそうでない場合、コードは機能しstaticます。

public synchronized void increase() {
    // method body
} 

と同等です

public void increase() {
    synchronized(this) {
        // method body
    }
}

countisであるため、とstaticの両方が異なるロックでアクセスしているため、非決定的な動作が発生します。共通ロックで同期化する (またはロック オブジェクトが正常に機能する) か、非静的にします。t1t2Runner4.increaseRunner4.classprivate staticcount

于 2013-02-10T02:35:55.840 に答える
0

あなたが望むものを達成しようとしている方法は、実際には最善の方法ではありません。それを行うためのより良い方法は、次のように Counter というクラスを定義することです。

public class Counter 
{
    int count;
    public Counter()
    {
        count = 0;
    }
    public synchronized void increase() {
        count++;
    }

    public int getCount()
    {
        return count;
    }

}

このクラスには、カウンターを増やして取得するメソッドがあります。次に行う必要があるのは、increase() メソッドを呼び出す 2 つのスレッドで共有される Counter オブジェクトを用意することです。したがって、スレッドクラスは次のようになります。

class Runner4 extends Thread {

    Counter count;
    public Runner4(Counter c)
    {
        count = c;
    }


    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            count.increase();
        }

    }
}

このクラスは Counter オブジェクトを受け取り、increase メソッドを呼び出すことに注意してください。また、クラスは Runnable を実装する代わりに Thread を拡張します。実際には大きな違いはありません。Runner4 が Thread クラスのメソッドを使用できるようになっただけです。

メインから Counter オブジェクトと 2 つの Runner4 スレッドを定義し、Counter オブジェクトをそれぞれに渡します。

public static void main(String[] args) {

        Counter count = new Counter();
        Thread t1 = new Runner4(count);
        t1.start();
        Thread t2 = new Runner4(count);
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(count.getCount());
    }
于 2013-02-10T02:42:44.367 に答える