2017-09-02 2 views
0

スレッドクラスを拡張するクラスAの2つのスレッドa1,a2を作成します。クラスAは2つのコンストラクタを宣言し、同期されたメソッドを実行します。Javaのsynchronizedキーワード

public class Main { 
    public static void main(String[] args) {  
     A t = new A() ;  
     A a1 = new A (t) ;  
     A a2 = new A (t) ; 

     a1.start(); 
     a2.start(); 
    }  
} 

class A extends Thread { 
    public A() { 
     super() ; 
    } 

    public A(Thread th) { 
     super(th) ; 
    } 
    @Override 
    public synchronized void run() { 
     for (int i = 0; i <13; i++) { 
      System.out.print(i+" ");    
     }  
    } 
} 

しかし、私:私はこのフォームでコードを書くときrunメソッドが同期として宣言されていると私は

0 0 1 1 2 3 4 5 6 7 2 8 3 9 4 10 5 11 6 12 7 8 9 10 11 12 

コードのような結果を取得していますが、2つのスレッドが時々同時に開始しますクラスThread介して2つのスレッドを作成し、

Thread a1 = new Thread (t); 
Thread a2 = new Thread (t); 

同期方法run仕事と2つのスレッドがで起動しませんではありませんなぜsynchronizedキーワード私はThraedクラスから2つのスレッドを作成するとき、私はクラスA(私は2つのコンストラクタを定義している)と、仕事から2つのスレッドを作成するときに動作しません:同じ時間は常に

0 1 2 3 4 5 6 7 8 9 10 11 12 0 1 2 3 4 5 6 7 8 9 10 11 12 

私の質問を結果を与えますか?

+2

スレッドが最初のケースで同時に起動するのはどうですか?混ざった出力が見えますか?その成果を見せてください。 –

+1

私は、 'synchronized'が実際に正しく動作していることを保証することができます。あなたは 'Thread'オブジェクト自体で同期していますが、これは本当に少し意味がありません。 –

+0

私の友人は正しく動作します。あなたの間違いはここで理解しています**スレッドa1 =新しいスレッド(t); Thread a2 = new Thread(t); ** small description = 2つの異なるロックを持つ2つの異なるオブジェクトを作成していますか?だから、なぜあなたはこれを持っていますか?どちらのスレッドも異なるロックを持っています。とった? –

答えて

1

はそれがThreadクラスで次のようになり、そのrun()メソッドを呼び出します:

public void run() { 
    if (target != null) { 
     target.run(); 
    } 
} 

このコードはnew Thread(Runnable target)に渡されたRunnable targetオブジェクトのrun方法からコードを実行する責任がありますコンストラクタ。

AクラスでThread#run()を上書きしました。だから今start()メソッドA#run(多形性のため)を呼び出す、つまりがAスレッドターゲットとして渡されたので、あなたのケースではt.run()を呼び出すことは決してありません(target.run())。
A#runメソッドが​​であっても、各スレッドが個別のインスタンス(スレッドオブジェクト自体)で呼び出すため、スレッドは共通のロック/モニタを使用していないため、同期は行われません。

あなたが正しい結果を得ようとするのは、あるスレッドが他のスレッドが起動する前に完全な作業を行うことができたからです。


はすべてでスレッドを拡張しないように紛らわしい問題(および他の多くの) を避けるために。 Runnableを実装するクラスを作成し、Threadインスタンスに渡します。 Runnableとしてタスク、そのタスクを実行する必要がありThreadとして労働者

と思います。あなたの仕事はどのように(..、それをつかむ、あなたの膝を曲げ)、(そこにそれを置く、これを取る)労働者が何をすべきかはない記述することです。

+0

お返事ありがとうございます –

0

Semaphore,CountDownLatchまたはCyclicBarrierのようなシンクロナイザを使用しない限り、スレッドが同時に開始することはありません。 ​​同じオブジェクト(メソッドまたはコードブロック)を同時アクセスから保護するために、キーワード自体が使用されます。あなたのコードで​​は役に立たない。あなたはいくつかの点でstart()を呼び出すことにより、スレッドを実行すると

0

以下は、問題を処理するための変更されたコードです。

public class RunnableDemo { 
    public static void main(String[] args) {  

     Object lock = new Object(); 
     Thread t1 = new Thread (new MyRunnable(lock));  
     Thread t2 = new Thread (new MyRunnable(lock));  

     t1.start(); 
     t2.start(); 
    }  
} 

class MyRunnable implements Runnable { 
    Object lock = new Object(); 
    public MyRunnable(Object lock){ 
     this.lock = lock; 
    } 

    @Override 
    public void run() { 
     synchronized(lock){ 
      for (int i = 0; i <13; i++) { 
       System.out.print(i+" ");    
      } 
     }   
    } 
} 
  1. Aはロックがメインクラスに作成される共有:RunnableDemo
  2. 2つのスレッドがRunnableインタフェースを実装MyRunnableオブジェクトを渡すことによって作成されています。新しいThreadを作成するようにThreadを拡張するのではなく、コンストラクタにRunnableインターフェイスの実装を渡すことが好ましい方法です。
  3. 両方のスレッドが開始されました。私は基本的なロック機構を展示している

    0 1 2 3 4 5 6 7 8 9 10 11 12 0 1 2 3 4 5 6 7 8 9 10 11 12 
    

:彼らは一般的なロックを共有しているので、一つだけThread完全run()ブロック

  • 今、あなたは以下のように出力が正しい順序である見ることができます。マルチスレッドの高度なバージョンについては、チュートリアルhigh level concurrencyを参照してください。

  • 関連する問題