簡體   English   中英

在靜態變量中使用同步

[英]Using synchronized in static variable

我有一張靜態地圖

private static Map<String, Car> cars = new HashMap<~>() //Map holding car objects

我在類似的方法中使用變量

private static String getCar(String name){
    return cars.get(name);
}

因此,如果我想鎖在汽車上,那么為了安全起見,可以像下面這樣做。

private static void xyz() {
    synchronized(cars) {
        Car c = getCar("abc");
        c.setColor("Green");
    }
}

有什么建議么?

Java的synchronized關鍵字可以應用於任何對象,以便在繼續操作之前對該對象“獲取鎖定”(或“對該對象進行同步”)。 如果任何其他進程嘗試同時運行在同一對象上同步的代碼,則它將阻塞,直到鎖定該對象的進程退出同步塊為止。

同步對象不必在synchronized塊的任何部分中實際使用; 它可能是一個簡單的互斥對象,其唯一目的是在同步塊中進行鎖定和解鎖。 但是,重要的是要注意,如果在對象上進行簡單同步,則如果其他線程也未在該對象上進行同步, 則不會阻止其他線程對其進行修改。 它是程序員/約定強制執行的鎖,而不是內置鎖,並且使用共享庫的所有代碼都必須“同意”才能在其上進行同步。

例如,使用您上面編寫的代碼,即使您的xyz()方法在cars同步,您也可以編寫這樣的另一種方法:

public void changeCar() {
    Car myCar = cars.get("abc");
    myCar.setColor("Blue");
}

修改cars 而沒有調用synchronized 這將有可能此方法修改的“ABC”的車在同一時間,作為方法xyz()正在修改它(即違反線程安全的),因為它不包含調用任何代碼synchronizedcars

如果要確保您的cars地圖是線程安全的(即,決不能同時用兩種方法修改),則必須

  1. 確保任何修改cars代碼都首先synchronized(cars)調用synchronized(cars)
  2. 使用ConcurrentHashMap ,以確保對其進行放置和獲取操作是線程安全的。

很好,但是請注意 ,在當前代碼中,您並沒有完全鎖定cars對象, 您仍然可以通過其他方法訪問cars並設置屬性, 除非再次在cars對象上進行同步

public static void otherMethod() {
  synchronized(cars) {
     Car myCar = cars.get("abc");
     myCar.setColor("Red");
  }
}

但是,如果方法xyz()是設置屬性的唯一位置 ,則您的代碼是線程安全的。

如果您只擔心單個方法的同步,請使用

Map<String, Car> synchronizedMap = Collections.synchronizedMap(map);

這將自動將同步添加到映射中的所有方法,並使每個方法調用為原子。 這是您可能應該公開給線程的映射。

但是,如果您需要在多個方法調用之間進行同步(如果為空,則在獲取后跟上put進行同步),則需要上述方法。

請注意,Car對象也需要也是線程安全的,並且在沒有看到該方法的情況下,我不能說它是否是。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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