2017-02-15 9 views
0

私はjavaでの同期を理解しようとしています。私は(最初に入力した誰でも)1つのスレッドを期待していた、上記の例から、 forループ同期メソッド

public class TestThr implements Runnable { 

    public static void main(String[] args) { 

      Thread t=new Thread(new TestThr()); 
      Thread t1=new Thread(new TestThr()); 

      t.start(); 
      t1.start(); 
    } 

    @Override 
    public void run() { 
     sync(); 
    } 

    public synchronized void sync(){ 
     for (int i=0;i<10;i++){ 
      System.out.println("Running "+Thread.currentThread().getName()); 
     } 
    } 

} 
 
Output : 
Running Thread-0 
Running Thread-1 
Running Thread-0 
Running Thread-1 
Running Thread-0 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-0 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 

を例を以下している反復を完了し、その後、第2の開始と完了しますが、私は一貫性のない出力を取得しています。

あなたの意見を加えてください。

ありがとうございます。

+0

は、あなたはそれがメソッドを同期させるために何を意味するのかについての説明は、*スタックオーバーフロー*を検索しましたか? – CKing

+0

@CKing申し訳ありませんが、同期メソッドの動作を理解できません。同じことを明確にするために私は尋ねた。 – dullpointer

答えて

3

これは次のようになります。このような

public synchronized void sync(){ 
    for (int i=0;i<10;i++){ 
     System.out.println("Running "+Thread.currentThread().getName()); 
    } 
} 

作品:

public void sync(){ 
     synchronize(this) { 
      for (int i=0;i<10;i++){ 
       System.out.println("Running "+Thread.currentThread().getName()); 
      } 
     } 
    } 

だから、あなたの場合には、各スレッドが異なるTestThrオブジェクトで同期する:

予想される出力を確認するには、次の試みることができます:

public class TestThr implements Runnable { 
    static SeparatedClass monitor; 

    public static void main(String[] args) { 
     monitor = new SeparatedClass(); 

     Thread t=new Thread(new TestThr()); 
     Thread t1=new Thread(new TestThr()); 

     t.start(); 
     t1.start(); 
    } 

    @Override 
    public void run() { 
     monitor.sync(); 
    } 
} 

class SeparatedClass { 
    public synchronized void sync(){ 
     for (int i=0;i<10;i++){ 
      System.out.println("Running "+Thread.currentThread().getName()); 
     } 
    } 
} 
+0

@DullPointerそれはこの答えで説明されているものです。あなたは* this *をロックしています。私は* this *が指摘していることをあなたが理解していると仮定していますか? – CKing

+0

'this'は' t'と 't1' @ Pavloを指しません。 'TestThr'の2つのインスタンスを指しています。 – Gray

+0

右私が間違えました。 –

3

上記の例から、1つのスレッド(最初に入力したもの)が繰り返しを完了し、次に2番目のスレッドが開始され、完了すると予想していましたが、一貫性のない出力が得られます。

出力が分かりませんが、作成したコードと一致しています。​​メソッドを使用している場合、囲むクラスのインスタンスをロックしています。あなたの例では

public class TestThr implements Runnable { 
    ... 
    public synchronized void sync() { 

sync方法は、それがTestThrの特定のインスタンスにロックします​​です。これは、各スレッドがTestThrの独自のインスタンスを持っているので、彼らは別のインスタンスにロックされ、実行されているから、お互いを停止しないことを意味し

Thread t = new Thread(new TestThr()); 
Thread t1 = new Thread(new TestThr()); 

:あなたはあなたのようなスレッドを開始しています。あなたの代わりに、以下を行った場合

は:

final TestThr testThr = new TestThr(); 
Thread t = new Thread(testThr); 
Thread t1 = new Thread(testThr); 

今、2つのスレッドはTestThrの同じインスタンス上で作業しているので、同じオブジェクト上でロックされ、あなたの出力は、あなたが期待したものになります。

これは、TestThrに格納されているフィールドがないためにのみ機能します。もっと複雑なクラスが必要な場合は、ロックオブジェクトを渡します。あなたはどうしたらあなたのコードの内部次に

final Object lockObject = new Object(); 
Thread t = new Thread(new TestThr(lockObject)); 
Thread t1 = new Thread(new TestThr(lockObject)); 

:何か

public void sync() { 
    synchronized (lockObject) { 
     ... 

だから、メソッドがロックされていないだろうが、あなたの代わりに共有ロックされたオブジェクトで同期う。

Btwでは、ループのサイズを考慮すると、あるスレッドがループを起動して実行し、他のスレッドが起動する前に終了する可能性が高くなります。 System.out.println(...)を呼び出すとスレッドが遅くなるため、競合が発生する可能性がありますが、出力を削除すると心配する必要があります。スレッド間の競合条件のために、このようなスレッドプログラムをテストすることは難しいかもしれません。

+0

大きな説明...ありがとうございました! – dullpointer

0

@Pavlo Plynkoが書いたように、synchronizedメソッドを使用していますが、Thread用に2つの異なるオブジェクトが作成されています。単一のインスタンスを作成し、このオブジェクトをスレッドに提供する必要があります。その場合、両方のスレッドはオブジェクトの同じインスタンスを使用し、同じメソッドの実行を待機します。

public class TestThr implements Runnable { 

public static void main(String[] args) { 
    TestThr synchronizedObject = new TestThr(); 
    Thread t = new Thread(synchronizedObject); 
    Thread t1 = new Thread(synchronizedObject); 

    t.start(); 
    t1.start(); 
} 

@Override 
public void run() { 
    System.out.println("Thread " + Thread.currentThread().getName() + " is waiting for execution"); 
    sync(); 
    System.out.println("Thread " + Thread.currentThread().getName() + " has executed synced method"); 
} 

public synchronized void sync() { 
    for (int i = 0; i < 10; i++) { 
     System.out.println("Running " + Thread.currentThread().getName()); 
    } 
} 
} 

は、次のような出力を提供します:コードに続いて

Thread Thread-0 is waiting for execution 
Thread Thread-1 is waiting for execution 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Running Thread-0 
Thread Thread-0 has executed synced method 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Running Thread-1 
Thread Thread-1 has executed synced method 
関連する問題