2012-02-14 91 views
26

原始數據類型是int & short在Java中是線程安全的嗎?我執行了下面的代碼,有些時候看不到預期的結果500。原始數據類型在Java中是線程安全的

public class SampleThree extends Thread 
{ 
    static long wakeUpTime = System.currentTimeMillis() + (1000*20); 
    static int inT; 
    public static void main(String args[]) 
    { 
     System.out.println("initial:" + inT); 
     for(int i=0; i<500; i++) 
      new SampleThree().start(); 
     try { 
      Thread.sleep(wakeUpTime - System.currentTimeMillis() + (1000*30)); 
      System.out.println("o/p:" + inT); 
     } 
     catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 

    public void run() 
    { 
     try { 
      long s = wakeUpTime - System.currentTimeMillis(); 
      System.out.println("will sleep ms: " + s); 
      Thread.sleep(s); 
      inT++; // System.out.println(inT); 
     } 
     catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

這裏同時有500個線程將更新int變量inT。主線程等待併發更新完成後,打印inT值。

找到類似的例子here

+9

不,它們不是線程安全的。如果你只打算閱讀,你應該考慮讓成員變成「volatile」。如果你打算從不同的線程讀取和寫入它,你應該使它成爲'同步的' – 2012-02-14 14:41:34

回答

45

有三種方式他們沒有安全:

  • longdouble甚至不保證用原子方式更新(你可以看到一半寫的從不同的線程)
  • 內存模型不保證你會看到從另一個線程中的一個線程的最新更新,沒有額外的內存障礙
  • 增量變量的行爲不是原子無論如何

使用AtomicInteger等進行線程安全操作。

4

我建議在java.util.concurrent.atomic中使用類。它們專爲線程安全而設計,並且在某些情況下,JVM可以利用硬件功能進行優化。

10

基本類型不是線程安全的。檢查this教程。

+0

關鍵的一點是,如果一個原語被定義爲一個對象實例的一部分,那麼這個原語將會在堆上,而不是線程安全。 – okwap 2015-02-09 13:56:18

+2

這很奇怪。 oracle文檔實際上說原始類型訪問對int來說是原子的:https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html – Yamcha 2017-05-22 14:47:12

+1

@Parvin,除了long和double之外,原始類型保證是原子。如果您正在讀取或寫入該值,則其線程可以安全地執行該操作。 – Pacerier 2017-09-20 02:39:31