簡體   English   中英

java多線程訪問原始變量

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM