併發 三 理解安全的發布

2021-08-03 18:31:12 字數 1114 閱讀 5404

我們常說,如果將物件放入到執行緒安全容器,例如vector或synchronizedmap時,那麼物件就可以安全地發布,後續的每個執行緒都可以安全地訪問。

按照我們上一節的論述,這裡的安全包含物件的內蘊狀態嗎,還是依舊僅僅只有物件的引用?

經過測試,我們可以發現,所有的執行緒安全容器依舊只能保證物件的引用更改是安全的,也就是說,只有當物件的引用位址發生了變化,其他執行緒才能感知到這種變化。

示例**如下,依舊以計數為例:

//  類本身不是執行緒安全的,絕不會因為放入執行緒安全容器,就會變成執行緒安全的類了

static class person

public

long

getage()

}

測試**如下:

final string key = "key";

final person person = new person();

// 放入執行緒安全容器

final mapvalues = collections.synchronizedmap(maps.newhashmap(key, person));

// 四個執行緒同時計數

for (int i = 0; i < 4; i++)

}}.start();

}

從結果來看,最後「person.getage()」依舊不能達到100的計數,所以物件的內容依舊不是執行緒安全的。

下面說簡單的解決辦法,因為物件的獲取是執行緒安全的,但遞增的方法(yiifaa.increment())是不安全的,所以只需要最小的鎖同步,如下:

person yiifaa = values.get(key);

// 當然觀察鎖也不一定要是yiifaa,只要是共享物件都可以,如key

synchronized(yiifaa)

count--;

從上面的**可以看出,鎖與共享變數並沒有直接的關係,只需要保證所有的執行緒在同乙個鎖上同步即可。

在使用synchronizedmap、synchronizedlist、concurrentmap時要千萬注意,執行緒安全容器僅僅只能保證物件的引用可見性,而不能內容的可見性。

併發程式設計(七) 安全發布物件

發布物件是指使乙個物件能夠被當前範圍之外的 所使用 物件逸出是一種錯誤的發布,指當乙個物件還沒有構造完成時,就使它被其他執行緒所見 slf4j public class escape private class innerclass escape.this thiscanbeescape publi...

併發學習(十) 安全物件發布

平時我們建立的物件往往不會考慮到安全物件的概念,這可能比較陌生,但是你面試的時候面試官很喜歡問你執行緒安全的單例模式,而這就是相關的知識點 發布 使物件能夠在除了當前作用域之外的地方使用 最常用的方法 將物件的引用儲存到乙個公有的靜態變數中,讓任何類和執行緒都能看到該物件。逸出 某個物件不應該被發布...

(二)Java併發學習筆記 安全發布物件

上邊關於逸出的概念講述的很是模糊,下面列舉幾個逸出的示例。通過靜態變數引用逸出 public static setknownsecrets public void initialize 上邊 示例中,呼叫initialize方法,發布了knowsecrets物件。當你向knowsecrets中新增乙...