2017-08-08 95 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 :Thread2

T2:線程1

T1:線程2

T2:線程1

T1:線程1

什麼情況?爲什麼不能將數據用作同步化的?

回答

5

您重新分配data的值。

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

這意味着Thread1獲得""對象上的鎖,然後Thread2獲得"Thread1"對象,它是一個完全不同的實體上的鎖。如果你想讓兩個線程在同一個對象上同步,你需要確保Thread1.data不會改變它指向的內容。最簡單的方法就是擁有一個單獨的鎖定對象。

public static final Object lock = new Object(); 

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

由於Thread1.lock永遠不會重新分配,它會永遠指向同一個對象,並推而廣之,同一把鎖。使它final將確保任何意外嘗試重新分配它將在編譯時失敗。

+2

也是一個很好的做法是鎖定對象'final'。 – Nikolay

+0

優秀點。編輯。 –

0

試試這個:

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

,因爲當您使用以下sentense對象鎖定數據總是變化: Thread1.data = 「線程1」; 所以你不能忍受兩個線程同步。