[英]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()
正在修改它(即違反線程安全的),因為它不包含調用任何代碼synchronized
上cars
。
如果要確保您的cars
地圖是線程安全的(即,決不能同時用兩種方法修改),則必須
cars
代碼都首先synchronized(cars)
調用synchronized(cars)
很好,但是請注意 ,在當前代碼中,您並沒有完全鎖定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.