2011-11-09 13 views
2

私は次のコードを持っている:スレッドと同期する方法

public class MyThread extends Thread { 
    private int i; 
    public static int sum=0; 
    public MyThread(int k){ 
     i=k; 
    } 




    public static void main(String[] args) throws InterruptedException{ 

     Thread t=new MyThread(1); 
     Thread s=new MyThread(2); 
     Thread p=new MyThread(3); 
     t.start(); 
     s.start();  
    } 


public synchronized void doSomething(){ 
    for(int i=0; i<100000; i++){ 
     System.out.println(this.i); 
    } 

} 

    @Override 
    public void run() { 
     doSomething(); 

    } 
} 

のdoSomethingが同期されています。なぜ出力はランダムですか? 私は、synchronizedメソッドはsynchronizedブロックと同じであるが、ブロックの出力はsyncであり、メソッドはそうでないと仮定します。

+0

「ランダム」とはどういう意味ですか?コードから、3つのスレッドが実行されているように見え、それぞれにプロセッサ時間が割り当てられ、出力はインターリーブされます。 – Nick

+0

@mary:私の例を見てください! –

答えて

8

​​キーワードは、で同期メソッド呼び出しが同じオブジェクトがインターリーブされないようにします。 異なるオブジェクトのインターリーブメソッド呼び出しを防ぎません。 3つのオブジェクトがあるので、3つの呼び出しは同時に実行できます。

3つのスレッドすべてで共有される単一のオブジェクトで同期する必要があります。

0

​​メソッドで使用されるロックは、クラスMyThreadのインスタンスに関連付けられています。各スレッドは独自のインスタンスMyThreadを持っているので、各スレッドは独自のロックで同期しています。

public class MyThread extends Thread { 

    private static final Object sharedLock = new Object(); 

    public void doSomething() { 
     synchronized(sharedLock) { 
     for(int i=0; i<100000; i++) { 
      System.out.println(this.i); 
     } 
     } 
    } 
    ... 
} 

代替がMyThread.classsynchronizeにですが、私は最初のアプローチを好む:あなたはすべてのスレッド間で同期したい場合は

は、あなたの線に沿って何かを行うことができます。

synchronized(this)doSomethingに使用するようにコードを変更した場合、そのコードはすべて突然動作します。私はそれがないと確信しています。偶然にはうまくいくかもしれませんが、繰り返して確実に動作することはありません。

+0

しかし、私はそれをsynchronized(this)に変更して内部にループを置くと順序付けされた結果が得られますが、同期はmythreadのクラスのインスタンスにあります – mary

+0

@mary:私の更新された答えをご覧ください。 – NPE

1

メソッドの同期は、同じオブジェクトの呼び出しに対してのみ保持されます。 2つの異なるオブジェクト(2つのスレッド)を作成しています。