2015-02-23 42 views
0

在這個程序中,對象jai被一個線程訪問,同時它也被另一個線程修改。這是正確的工作方式嗎?是否不需要使對象同步?變量的同步

public class SameObjectModification { 

    private static int i = 0; 

    private static Jai jai; 

    static class Jai { 

     private final int a; 

     public Jai(int a) { 
      this.a = a; 
     } 

     public void print() { 
      System.out.println("value ==> " + a); 
     } 
    } 

    public static void main(String[] args) { 

     Thread t1 = new Thread() { 

      @Override 
      public void run() { 
       while (true) { 
        if (jai != null) 
         jai.print(); 
       } 
      } 
     }; 

     Thread t2 = new Thread() { 

      @Override 
      public void run() { 
       while (true) { 
        jai = new Jai(i++); 
       } 
      } 
     }; 

     t1.start(); 
     t2.start(); 
    } 
} 
+0

你想達到什麼目的? – aioobe 2015-02-23 10:22:09

+1

不,不是。您正在從不同的線程訪問狀態。所以你會有可見性問題。 – 2015-02-23 10:23:39

+0

這取決於你想要的。如果你想實現互斥,那麼你必須同步它。 – 2015-02-23 10:39:06

回答

0

目前尚不清楚你試圖達到什麼目標,但是你可以通過使用原子來獲得每個Jai的唯一值。

private static AtomicInteger i = new AtomicInteger(0); 

private static Jai jai; 

static class Jai { 

    private int a; 
    public Jai() { 
     this.a = i.incrementAndGet(); 
    } 
0

這thrade保存例如

private static int i = 0; 

private static AtomicReference<Jai> jai = new AtomicReference<Jai>(); 

static class Jai { 

    private final int a; 

    public Jai(int a) { 
     this.a = a; 
    } 

    public void print() { 
     System.out.println("value ==> " + a); 
    } 
} 

public static void main(String[] args) { 

    Thread t1 = new Thread() { 

     @Override 
     public void run() { 
      while (true) { 
       Jai tmp = jai.get(); 
       if (tmp != null) 
        tmp.print(); 
      } 
     } 
    }; 

    Thread t2 = new Thread() { 

     @Override 
     public void run() { 
      while (true) { 
       jai.set(new Jai(i++)); 
      } 
     } 
    }; 

    t1.start(); 
    t2.start(); 
} 

的版本,但實現取決於porpose。 您應該只對不可變或線程安全的類使用AtomicReference。

在其他情況下,您可以使用不同的鎖,易失性字段,不同的原子實現(如AtomicLong)或同步。

但是你應該記住一個比鎖和一個鎖更快的原子比同步更快。

+0

我想知道爲什麼我沒有得到任何異常,當我運行此代碼。 – LPD 2015-02-23 10:54:13

+1

您不會在您的代碼中發現任何異常,因爲引用下的操作通常是CPU架構(例如x86)的原子操作。但是如果你在異國情調的CPU上運行你的代碼,你可能會得到異常。 – SergSW 2015-02-23 11:06:02

0

實際上,變量jai依次引用許多對象。在第二個線程的循環的每次迭代中,都會創建一個新對象並將其分配給該變量。所以,在jai上同步將無濟於事。

如果你想確保由t2線程創建的所有對象由t1處理,你需要或者鎖T1,等待t2創建對象或使用一種隊列。閱讀關於java.util.concurrent.BlockingQueue

更一般地,這是Producer-Consumer問題的一個例子。