[英]java multi thread access to primitive variables
我知道同時從不同的線程訪問同一個對象,沒有同步,通常是一件壞事。 但是這個案子呢:
我有多個線程在運行(考慮兩個,ThreadA和ThreadB)。 我也有這個靜態類來保持Thread執行某些操作的次數。
public class Counter {
static private int counter=0;
static public void incCounter() {
counter++;
}
}
如果ThreadA和ThreadB都調用Counter.incCounter()會發生什么?
這不安全。
每個線程將嘗試讀取counter
,向其添加一個,並回寫結果。 您無法保證這些讀寫操作的順序,或者即使結果對每個線程都可見。
特別是,一個失敗的情況是每個線程讀取值0,將其遞增為1,並寫回值1.即使在兩個線程嘗試遞增它之后,這也會使計數器的值為1。
請考慮使用AtomicInteger .incrementAndGet()。
它的值可以是1或2.在這種情況下,靜態和非靜態變量之間沒有區別。
它是靜態對象還是實例無關緊要:如果從多個線程更改它,您將遇到問題。
為避免沖突,請使用關鍵字synchronized。
public class Counter {
static private int counter=0;
public static synchronized void incCounter() {
counter++;
}
}
這個關鍵字只允許一個時間線程來調用incCounter()。
Dave是正確的,但快速修復只是將“synchronized”關鍵字添加到該方法描述中; 如果多個線程調用該方法,它們將在方法邊界處阻塞,直到內部的一個(贏得比賽)增加並存在,然后第二個調用者將進入。
這就像在Singleton類上設計一個好的“getInstance()”方法一樣; 你通常希望它被同步,所以你沒有2+個線程進入方法的情況,ALL看到“instance”為null,然后ALL創建一個新實例,將它分配給本地成員並返回它。
在這種情況下,您的線程可能會以“相同”實例的不同引用結束。 因此,您同步代碼塊,只允許第一個線程創建實例(如果它為null),否則始終將相同的實例返回給所有調用者。
if(instance == null)檢查加上返回便宜; 對於將來調用getInstance(或者在你的示例中為incCounter),我相信微秒的順序,所以如果你需要,不需要回避synchronized關鍵字; 這就是它的用途。
話雖如此,如果你不能節省微秒......那么你可能會使用錯誤的語言:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.