2012-07-18 97 views
0

如果多個線程讀取之前已設置且以後不會更改的基本類型,它們是否會得到錯誤的值?多線程讀取原始類型

例如,假定下面的簡單代碼摘錄:

public static final boolean proceed = read(); // Read the value from a file 

public static void doSomething() // Method accessed by multiple threads 
{ 
    if (proceed) 
    { 
     System.out.println("TRUE"); 
    } 
    else 
    { 
     System.out.println("FALSE"); 
    } 
} 

假設proceed變量初始化爲true,是有可能的是,在一個或多個所述多個線程的同時運行的doSomething()方法,打印的信息是FALSE

如果proceed變量是可變的,肯定這是可能的,因此需要同步或者使用AtomicBoolean(例如根據this question)。但在這種情況下,proceed是不可變的,只能在包含類的靜態初始化期間設置一次。

對於其他基元類型,類似地,如果一個值被設置爲final,那麼它應該始終是線程安全的,以後再訪問它,對嗎?

回答

1

事實上,你的變量是final保證所有的線程都會在一致的後初始化狀態下看到它。這也適用於對象的引用(即,如果對象已被初始化爲非空引用,則所有線程都將看到該對象的非空值 - 但是如果對象不是線程安全的,則某些線程可能會看到對象本身不一致或陳舊的狀態)。

ps:這是假設你的讀取方法不嘗試讀取布爾值,在這種情況下,它會看到默認(false)值。

1

由於proceedstaticfinal,因此無法重新分配,從而導致線程安全。

static說它是級別級別,並且final表示它的值不能更改,這是一個primitive所以這是不可改變的,因此是線程安全的。

1

你說這是不可改變的(static and final),所以我們可以放心地說它是線程安全的。

1

該引用是線程安全的,因爲它是不可變的。

如果它是可變的,則需要使用volatile關鍵字來確保在另一個線程中修改了最新值。

Do you ever use the volatile keyword in Java?

+1

雖然雙和長您的評論是準確的,但並不適用於這個問題。使用double而不是boolean的問題會得到相同的答案。 – assylias 2012-07-18 13:19:26