5

次のコードを実行しました。

class Counter extends Thread {

 static int i=0;
//method where the thread execution will start
public void run(){
    //logic to execute in a thread

    while (true) {
        increment();
    }
}

public synchronized void increment()  {
    try {
        System.out.println(this.getName() + " " +  i++);
        wait(1000);
        notify();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
//let’s see how to start the threads
public static void main(String[] args){
    Counter c1 = new Counter();
    Counter c2 = new Counter();
    c1.setName("Thread1");
    c2.setName("Thread2");
    c1.start();
    c2.start();
}
}

このコードの結果は (追加された行番号):

1: Thread1 0
2: Thread2 1
3: Thread2 2
4: Thread1 3
5: Thread2 4
6: Thread1 4
7: Thread1 5
8: Thread2 6
stopping...

インクリメントメソッドは同期されており、wait(1000) が含まれているため、期待していませんでした: 1. スレッド 2 が 2 つの連続した印刷を印刷する: 行 2,3 スレッドが印刷をインターリーブすることを期待しました 2. 行 5,6 で、i は 4 のままです。

誰か私にこれについて説明してもらえますか?

4

3 に答える 3

9

次のような同期されたインスタンス メソッド:

public synchronized void foo() { 
    ... 
}

以下とほぼ同等です。

public void foo() {
   synchronized(this) {
       ...
   }
}

ここに問題がありますか?同期は現在のインスタンスで行われます。

2 つの別個Threadのオブジェクトを作成しているため、各incrementメソッドは異なるオブジェクトで同期するため、ロックが役に立たなくなります。

インクリメント メソッドを静的にする (つまり、ロックはクラス自体で行われる) か、静的ロック オブジェクトを使用する必要があります。

private static final Object locker = new Object();

public void foo() {
   synchronized(locker) {
       ...
   }
}

最後に 1 つのアドバイス: Java でスレッドを作成するための推奨される方法はRunnable、 を拡張するのではなく、を実装することThreadです。

于 2012-05-19T12:26:06.867 に答える
1

インスタンスレベルでのみ同期しています。すべてのCounterインスタンス間で同期するには、incrementメソッドstaticsynchronized.

現状では、同期メカニズムを共有していないため、すべてのスレッドが互いに並行して自由に実行されます。

于 2012-05-19T12:22:55.930 に答える
0

これはおそらくあなたが探しているコードです

class Counter implements Runnable {

    static int i = 0;
    private Lock lock;
    private Condition condition;

    public Counter(Lock lock, Condition condition) {

        this.lock = lock;
        this.condition = condition;
    }


    public void run() {
        while (true) {
            lock.lock();
            try {
                condition.await(1, TimeUnit.SECONDS);
                System.out.append(Thread.currentThread().getName()).append(" ").println(i++);
                condition.signalAll();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        Lock lock = new ReentrantLock(true);
        Condition condition = lock.newCondition();
        Executor e = Executors.newFixedThreadPool(2);
        e.execute(new Counter(lock, condition));
        e.execute(new Counter(lock, condition));

    }
}
于 2012-05-19T13:12:32.943 に答える