2017-07-21 17 views
1

私はJavaで同期メソッドの概念を把握しようとしていますが、少なくとも私にとっては混乱しているような動作に遭遇しました。 Iは、INC()メソッドの同期の使用が順次インクリメントをもたらすことが期待Java同期メソッドの使用

Thread[Thread-0,5,main] 
Thread[Thread-1,5,main] 
Thread[Thread-0,5,main] 
Thread[Thread-1,5,main] 
Thread[Thread-1,5,main] 
Thread[Thread-0,5,main] 
Thread[Thread-0,5,main] 
Thread[Thread-1,5,main] 

public class parallelUpdate 
{ 
    public static void main(String[] args) 
    { 
     Ob ob = new Ob(); 
     new Thread(ob).start(); 
     new Thread(ob).start(); 
    } 
} 

class Ob implements Runnable 
{ 
    static int cnt = 0; 

    private synchronized void inc() 
    { 
     cnt++; 
    } 

    @Override 
    public void run() 
    { 
     for (int i = 0; i < 5; i++) { 
      System.out.println(Thread.currentThread()); 
      inc(); 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

...インクリメントが両方のトレッドにより並行して行われる:コードで like:

Thread[Thread-0,5,main] 
Thread[Thread-0,5,main] 
Thread[Thread-0,5,main] 
Thread[Thread-0,5,main] 
Thread[Thread-0,5,main] 
Thread[Thread-1,5,main] 
Thread[Thread-1,5,main] 
Thread[Thread-1,5,main] 
Thread[Thread-1,5,main] 
Thread[Thread-1,5,main] 

私のコードに間違いがありますか?

+1

'inc()'メソッドの代わりに 'run()'メソッドを 'synchronized'にしてみてください。 – Jesper

+0

スレッドを処理するために 'atomic Integer'クラスのメソッドを使用します。 –

+3

" inc()メソッドでsynchronizedを使用すると、シーケンシャルなインクリメントが得られると思います。 'inc'メソッドのみを同期しました。つまり、2つのスレッドで並列に実行することはできませんが、特定の実行順序になるわけではありません。 – talex

答えて

0

嘆願が正しいコードを見つける: - あなたのコードに対する

public class parallelUpdate { 
     public static void main(String[] args) { 
      Ob ob = new Ob(); 
      new Thread(ob).start(); 
      new Thread(ob).start(); 

     } 
    } 


    class Ob implements Runnable { 
     static int cnt = 0; 
     private synchronized void inc() { 
       for (int i = 0; i < 5; i++) { 
        System.out.println(Thread.currentThread()); 
        cnt++; 
        try { 
         Thread.sleep(100); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
     } 
     @Override 
     public void run() { 
      inc(); 
     } 
    } 

説明: - )(

あなたが作っている株式会社は、メソッドは同期されていますが、**for loop**では同期されていませんので、2つのトレッドに入ってinc();同期操作を実行します。

0

これはスレッドスケジューラが実行するスレッドを決定し、スレッドを選択する特定の順序がないためです。スレッドで優先度を設定できますが、スケジューラが選択するかどうかは同じです。スケジューラに特定のスレッドを実行するように依頼できますが、強制はしません。 メソッドを同期させると、そのメソッドは一度に1つのスレッドによってのみ実行されます。 スレッドを作成、維持、破棄するためのよりクリーンな方法を提供するThread Executers APIをチェックすることも助言します。 ここでは、Javaのスレッド上の有用なリンクです:http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/

0

スレッド1の後にスレッド2開始はその後、より良い解決策は、結合方法を使用する場合、そのプログラムは2

how wait for a thread to finish...

public static void main(String[] args) { 
     Ob ob = new Ob(); 
     Thread myFirstThread = new Thread(ob); 
     myFirstThread.start(); 

     try { 
      myFirstThread.join(); 
     } catch (InterruptedException e) { 

      e.printStackTrace(); 
     } 

     Thread mySecondThread = new Thread(ob); 
     mySecondThread.start(); 

    } 

ゴースレッドを開始するスレッド1フィニッシュまで望むことを意味します Synchronized Methos

  • 最初にどのように動作するかsyncrhonized方法を明確にするJavaドキュメントには、同期の2つの呼び出しのために可能ではありませんインターリーブするために同じオブジェクト上にメソッドを実装しました。あるスレッドがオブジェクトの同期メソッドを実行しているとき、そのオブジェクトで最初のスレッドが完了するまで、同じオブジェクトブロックの同期メソッドを呼び出す他のすべてのスレッド(実行を中断)。
  • 第2に、同期メソッドが終了すると、同じオブジェクトに対する同期メソッドのその後の呼び出しと自動的に「先行」関係が確立されます。これにより、オブジェクトの状態の変更がすべてのスレッドで認識できることが保証されます。
関連する問題