2017-08-08 129 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”; 所以你不能忍受两个线程同步。