日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

并发编程-08安全发布对象之发布与逸出

發布時間:2025/3/21 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程-08安全发布对象之发布与逸出 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 腦圖
  • 概念
  • 示例
    • 不安全的發布對象Demo
    • 對象逸出Demo
  • 小結
  • 代碼

腦圖


概念

發布對象: 使一個對象能夠被當前范圍之外的代碼所使用,日常開發中比較常見的比如通過類的非私有方法返回對象的引用,或者通過公有的靜態變量發布對象 等都屬于發布對象

對象逸出: 首先需要明確的是對象逸出是一種錯誤的發布方式。 當一個對象還沒有構造完成時,就使它被其他線程所見。


示例

不安全的發布對象Demo

package com.artisan.example.publish;import com.artisan.anno.NotThreadSafe;import lombok.extern.slf4j.Slf4j;@Slf4j @NotThreadSafe public class UnSafePublishObjectDemo {// 私有變量private String name = "artisan";// 通過public訪問級別的方法getName發布了類的域,在類的外部,任何線程都可以訪問這個域// 這樣發布的對象是不安全的,因為我們無法得知其他線程是否會修改這個域導致該類里數據的錯誤public String getName() {return name;}public static void main(String[] args) {// 通過new實例化UnSafePublishObjectDemoUnSafePublishObjectDemo unSafePublishObjectDemo = new UnSafePublishObjectDemo();// 調用getName()方法得到私有屬性的引用String name = unSafePublishObjectDemo.getName();log.info("name:{}",name);// 假設有第二個線程去修改name屬性的值String name2 = unSafePublishObjectDemo.getName();name2 = "小工匠";log.info("name:{}",name2);}}

上面的代碼里,通過new對象初始化了UnSafePublishObjectDemo對象。然后調用getName()方法獲取到了私有屬性的引用,這樣就可以在其他任何線程中,修改該屬性的值。這樣將會導致我們在其他線程中,獲取該屬性的值時是不確定的,因為并不能得知該屬性的值是否已被其他線程所修改過,所以這就是不安全的對象發布。


對象逸出Demo

package com.artisan.example.publish;import com.artisan.anno.NotRecommand; import com.artisan.anno.NotThreadSafe;import lombok.extern.slf4j.Slf4j;/*** * 對象逸出示例,在對象構造完成之前,不可以將其發布* @author yangshangwei**/ @Slf4j @NotThreadSafe @NotRecommand public class ObjectEscapeDemo {private int thisCanBeEscape = 0;public ObjectEscapeDemo() {new InnerClass();}private class InnerClass {// this引用的逸出// 內部類的構造器里包含了對封裝實例的隱含引用,這樣在對象沒有被正確構造完成之前就會被發布,由此會導致不安全的因素在里面public InnerClass() {log.info("{}", ObjectEscapeDemo.this.thisCanBeEscape);}}public static void main(String[] args) {new ObjectEscapeDemo();}}

上述代碼中,內部類的構造器里包含了對封裝實例的隱含引用,這樣在對象沒有被正確構造完成之前就會被發布,由此會導致不安全的因素在里面。

其中一個就是導致this引用在構造期間逸出的錯誤,它是在構造函數構造過程中啟動了一個線程,無論是顯式啟動還是隱式啟動,都會造成this引用的逸出

新線程總會在所屬對象構造完畢之前就已經看到它了,所以如果要在構造函數中創建線程,那么不要啟動它,而是應該采用一個專有的start,或是其他初始化的方式統一啟動線程。

這里其實我們可以使用工廠方法和私有構造函數來完成對象創建和監聽器的注冊等等來避免不正確的發布。


小結

不正確的發布可變對象導致的兩種錯誤:

  • 發布線程以外的所有線程都可以看到被發布對象的過期的值
  • 線程看到的被發布對象的引用是最新的,然而被發布對象的狀態卻是過期的

代碼

https://github.com/yangshangwei/ConcurrencyMaster

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的并发编程-08安全发布对象之发布与逸出的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。