2017-08-08 18 views
0
public class Thread1 extends Thread { 
public static String data = "" ; 
public Thread1(String tname){ 
    super(tname); 
} 
public void run(){ 
    synchronized (Thread1.data){ 
     for (int i = 0; i < 5; i++) { 
      if(this.getName().equals("T1")){ 
       Thread1.data = "Thread1"; 
       try { 
        Thread.sleep(1000); 
       }catch (InterruptedException e){} 
       System.out.println(getName()+":"+Thread1.data); 
      }else if (this.getName().equals("T2")){ 
       Thread1.data = "Thread2"; 
       try { 
        Thread.sleep(1000); 
       }catch (InterruptedException e){} 
       System.out.println(getName()+":"+Thread1.data); 
      } 
     } 
    } 
} 
} 

public class Main { 

public static void main(String[] args) { 
    Thread a1 = new Thread1("T1"); 
    Thread a2 = new Thread1("T2"); 
    a1.start(); 
    a2.start(); 
} 
} 

出力: T2:スレッド2Javaの静的およびスレッド安全

T1:スレッド2

T2:スレッド1

T1:スレッド2

T2:スレッド1

T1 :スレッド2

T2:スレッド1

T1:スレッド2

T2:スレッド1

T1:スレッド1

状況は何ですか?データを同期化して使用できないのはなぜですか?

答えて

5

dataの値を再割り当てします。

Thread1.data = "Thread1"; 
// ... 
Thread1.data = "Thread2"; 

これはThread1""オブジェクトのロックを取得し、Thread2は完全に異なるエンティティである"Thread1"オブジェクトのロックを取得することを意味します。 2つのスレッドを同じオブジェクトで同期させたい場合は、Thread1.dataが何を指しているのかを変更しないようにする必要があります。これを行う最も簡単な方法は、個別のロックオブジェクトを持つことです。 Thread1.lock以来

public static final Object lock = new Object(); 

// Then, inside the function... 
synchronized (Thread1.lock) { 
    // ... 
} 

が再割り当てされることはありません、それは常に、拡張子によって、同じロックを同じオブジェクトを参照してします。 finalにすることで、誤って再割り当てしようとするとコンパイル時に失敗することがあります。

+2

また、ロックオブジェクトを「最終」にすることをお勧めします。 – Nikolay

+0

優れたポイント。編集されました。 –

0

この試してください:あなたは、次のsentense使用するときにオブジェクトのロックデータは常に変更されるため

public void run() { 
     synchronized (Thread1.class) { 
      for (int i = 0; i < 5; i++) { 
       ... 
      } 
     } 
    } 

を: Thread1.data = "スレッド1" を。 2つのスレッドを同期させることはできません。

関連する問題