2

run()私たちが知っているように、メソッドを使用して複数のスレッドがメソッドを呼び出すのを防ぐための規定はありませんstart()。2 つのオブジェクトm1を作成し、m2両方とも同じスレッドを呼び出して実行しました。

m1.start2 番目のオブジェクトの実行が開始される前に、スレッドを呼び出して、最初のオブジェクトの実行が終了 () されていることを確認する必要があります。

私の質問は、私が作成したスレッド (つまり)でメソッドでsynchronizedキーワードを使用できないのはなぜですか?run()MyThread1

作成したスレッドでrun()メソッドに「同期」を使用しようとしましたが、任意の出力が得られます(つまり、実行が完了m2するのを待ちません)。m1

プログラムの一番下に、私が取得している出力が表示されます。

public class ExtendedThreadDemo {

    public static void main(String[] args) {    
        Mythread1 m1 =new Mythread1();
        Mythread1 m2 =new Mythread1();
        m1.start();
        m2.start();
        System.out.println(" main thread exiting ....");
    }
}

マイスレッド

public class MyThread1 extends Thread {

    public synchronized void run() {
        for(int i=1; i<5; i++) {
            System.out.println(" inside the mythread-1 i = "+ i);
            System.out.println(" finish ");

            if (i%2 == 0) {
                try {
                    Thread.sleep(1000);
                } catch(InterruptedException e) {
                     System.out.println(" the thread has been interrupted ");
                }
            }
        }
    }
}

出力

main thread exiting ....
inside the mythread-1 i = 1
finish
inside the mythread-1 i = 2
finish 
inside the mythread-1 i = 1
finish 
inside the mythread-1 i = 2
finish 
inside the mythread-1 i = 3
finish 
inside the mythread-1 i = 4
finish 
inside the mythread-1 i = 3
finish 
inside the mythread-1 i = 4
finish 

の後でわかるようにi = 2、2 番目のオブジェクト (つまりm2.start()) が実行を開始しました。

4

3 に答える 3

2

呼び出す前に呼び出しm1.join()ます。mainm2.start()

メソッドの作成は、同じオブジェクトsynchronizedのメソッドへの複数の呼び出しにのみ影響します。とは異なるオブジェクトなので、追加しても効果はありません。m1m2synchronized

于 2012-05-26T14:58:25.053 に答える
0

このコード スニペット:

public synchronized void run() {
  //code
}

意味的には次と同等です。

public void run() {
  synchronized(this) {
    //code
  }
}

参照に注意してthisください。これはsynchronized、同じ参照 (ロック オブジェクト) を使用するすべてのブロックthisが相互に排他的であることを意味します。ただし、2 つのスレッド (オブジェクト) を作成していますが、それぞれが異なるthis参照で同期しています。

コードを改善するには、いくつかの方法があります。

1 つのみを使用Runnableして、2 つのスレッドを作成します。

public class Mythread1 implements Runnable //...

その後:

Runnable r = new Mythread1();
Thread m1 = new Thread(r);
Mythread1 m2 = new Thread(r);

ただし、これはMythread12 つのスレッドで共有されるため、 runnable がステートレスである場合にのみ機能します。

同じロック インスタンスを使用する

lockの両方のインスタンスに任意のオブジェクトを渡してからMythread1、次を使用します。

synchronized(lock) {
  //code
}

Java 5 以降、コードを同期するためのはるかに洗練された方法がありますが、単純なケースではこれで十分です。

使用するThread.join()

あなたは呼び出すことができます:

m1.start();
m1.join();
m2.start();

これでうまくいきます。

于 2012-05-26T15:01:12.093 に答える
0

同期インスタンス メソッドは、クラスの同じインスタンスへの同時アクセスを妨げるだけです。run メソッドが静的である場合、期待どおりの効果が得られます。しかし、run メソッドを静的にすることはお勧めしません。実際、現在の機能を維持する場合はできません。代わりに考慮すべきことはm1.join()、 m1 が終了するのを待つために使用することです。互いに待機する複数のスレッドがある場合にうまく機能する別のアプローチは、CyclicBarrierまたはCountDownLatchを使用することです。

于 2012-05-26T15:03:01.443 に答える