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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

并发编程-09安全发布对象+单例模式详解

發(fā)布時間:2025/3/21 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程-09安全发布对象+单例模式详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 腦圖
  • 概述
  • 安全發(fā)布對象的4種方式
  • 示例
    • 懶漢模式(線程不安全)
    • 餓漢模式 靜態(tài)域(線程安全)
    • 改造線程不安全的懶漢模式方式一 靜態(tài)方法使用synchronized修飾 (線程安全)
    • 改造線程不安全的懶漢模式方式二雙重檢查機制(線程不安全)
    • 改造線程不安全的懶漢模式方式二雙重檢查機制優(yōu)化-volatile + 雙重檢測機制 (線程安全)
    • 餓漢模式的第二種寫法 靜態(tài)代碼塊 (線程安全)
    • 餓漢模式的第三種寫法 靜態(tài)內(nèi)部類 (線程安全)
    • 小結(jié)
  • 枚舉模式 推薦 ( 線程安全,防止反射構(gòu)建)
  • 代碼

腦圖


概述

上篇文章并發(fā)編程-08安全發(fā)布對象之發(fā)布與逸出中簡單的描述了下對象發(fā)布和逸出的概念,并通過demo演示了不安全發(fā)布對象對象逸出(this引用逸出)。 那該如何安全的發(fā)布對象呢?


安全發(fā)布對象的4種方式

  • 在靜態(tài)初始化函數(shù)中初始化一個對象的引用

  • 將對象的引用保存到volatile類型域或者AtomicReference對象中

  • 將對象的引用保存到某個正確構(gòu)造對象的final類型域中

  • 將對象的引用保存到一個由鎖保護的域中


示例

上面所提到的幾種方法都可以應(yīng)用到單例模式中,我們將以單例模式為例,介紹如何安全發(fā)布對象,以及單例實現(xiàn)的一些注意事項。

以前寫的一篇文章: 單例模式

懶漢模式(線程不安全)

package com.artisan.example.singleton;import com.artisan.anno.NotThreadSafe;/*** 懶漢模式 單例的實例在第一次調(diào)用的時候創(chuàng)建* * 單線程下沒問題,多線程下getInstance方法線程不安全* * @author yangshangwei**/ @NotThreadSafe public class SingletonLazyModel {// 私有構(gòu)造函數(shù)// 如果要保證一個類只能被初始化一次,首先要保證的是構(gòu)造函數(shù)是私有的,不允許外部類直接調(diào)用new方法private SingletonLazyModel() {// 可以初始化一些資源等}// static單例對象private static SingletonLazyModel instance = null;// 靜態(tài)工廠方法 // public方法外部通過getInstance獲取public static SingletonLazyModel getInstance() {// 多線程情況下,假設(shè)線程A和線程B同時獲取到instance為null, 這時候instance會被初始化兩次if (instance == null) {instance = new SingletonLazyModel();}return instance;}}

餓漢模式 靜態(tài)域(線程安全)

package com.artisan.example.singleton;import com.artisan.anno.ThreadSafe;/*** 餓漢模式 單例的實例在類裝載的時候進行創(chuàng)建* * 因為是在類裝載的時候進行創(chuàng)建,可以確保線程安全* * * 餓漢模式需要注意的地方: 1.私有構(gòu)造函數(shù)中不要有太多的邏輯,否則初始化會慢 2.確保初始化的對象能夠被使用,否則造成資源浪費* * @author yangshangwei**/ @ThreadSafe public class SingletonHungerModel {// 私有構(gòu)造函數(shù)// 如果要保證一個類只能被初始化一次,首先要保證的是構(gòu)造函數(shù)是私有的,不允許外部類直接調(diào)用new方法private SingletonHungerModel() {// 可以初始化一些資源等}// static單例對象 靜態(tài)域private static SingletonHungerModel instance = new SingletonHungerModel();// public方法外部通過getInstance獲取public static SingletonHungerModel getInstance() {// 直接返回實例化后的對象return instance;}}

改造線程不安全的懶漢模式方式一 靜態(tài)方法使用synchronized修飾 (線程安全)

僅需要將靜態(tài)的 getInstance方法使用synchronized修飾即可,但是缺點也很明顯,線程阻塞,效率較低

synchronized修飾靜態(tài)方法的作用域及demo見 并發(fā)編程-05線程安全性之原子性【鎖之synchronized】


改造線程不安全的懶漢模式方式二雙重檢查機制(線程不安全)

改造線程不安全的懶漢模式方式一 靜態(tài)方法使用synchronized修飾的缺點既然都清楚了,為了提高效率,那就把synchronized下沉到方法中的實現(xiàn)里吧

package com.artisan.example.singleton;import com.artisan.anno.NotThreadSafe;/*** 懶漢模式 單例的實例在第一次調(diào)用的時候創(chuàng)建* * 對static getInstance方法 進行 雙重檢測* * @author yangshangwei**/ @NotThreadSafe public class SingletonLazyModelOptimize2 {// 私有構(gòu)造函數(shù)// 如果要保證一個類只能被初始化一次,首先要保證的是構(gòu)造函數(shù)是私有的,不允許外部類直接調(diào)用new方法private SingletonLazyModelOptimize2() {// 可以初始化一些資源等}// static單例對象private static SingletonLazyModelOptimize2 instance = null;// 靜態(tài)工廠方法// public方法外部通過getInstance獲取public static SingletonLazyModelOptimize2 getInstance() {// 多線程情況下,假設(shè)線程A和線程B同時獲取到instance為null, 這時候instance會被初始化兩次,所以在判斷中加入synchronizedif (instance == null) {// synchronize修飾類 ,修飾范圍是synchronized括號括起來的部分,作用于所有對象synchronized(SingletonLazyModelOptimize2.class) {if (instance == null) {instance = new SingletonLazyModelOptimize2();}}}return instance;}}

先說下結(jié)論: 上述代碼是線程不安全的,可能會返回一個未被實例化的instance,導(dǎo)致錯誤。

這個就要從cpu的指令說起了。

問題主要出在實例化這一步

instance = new SingletonLazyModelOptimize2()

這個實例化的操作,對應(yīng)底層3個步驟

  • memory = allocate() // 分配對象的內(nèi)存空間
  • ctorInstance() // 初始化對象
  • instance = memory // 設(shè)置instance指向剛分配的內(nèi)存
  • 對于單線程,肯定是沒有問題的。但是對于多線程,CPU為了執(zhí)行效率,可能會發(fā)生指令重排序。

    經(jīng)過JVM和CPU的優(yōu)化,因為第2步和第2步本質(zhì)上沒有先后關(guān)系,指令可能會重排成下面的順序 1—>3—>2:

    • 1.memory = allocate() // 分配對象的內(nèi)存空間
    • 3.instance = memory // 設(shè)置instance指向剛分配的內(nèi)存
    • 2.ctorInstance() // 初始化對象

    假設(shè)按照這個指令順序執(zhí)行的話,那么當線程A執(zhí)行完1和3時,instance對象還未完成初始化,但已經(jīng)不再指向null。此時如果線程B搶占到CPU資源,執(zhí)行 if (instance == null)的結(jié)果會是false,從而返回一個沒有初始化完成的instance對象


    改造線程不安全的懶漢模式方式二雙重檢查機制優(yōu)化-volatile + 雙重檢測機制 (線程安全)

    經(jīng)過volatile的修飾,保證變量的可見性,當線程A執(zhí)行instance = new SingletonLazyModelOptimize3的時候,JVM執(zhí)行順序會始終保證是下面的順序:

    • 1.memory = allocate() // 分配對象的內(nèi)存空間
    • 2.ctorInstance() // 初始化對象
    • 3.instance = memory // 設(shè)置instance指向剛分配的內(nèi)存

    這樣的話線程B看來,instance對象的引用要么指向null,要么指向一個初始化完畢的Instance,而不會出現(xiàn)某個中間態(tài),保證了線程安全。


    餓漢模式的第二種寫法 靜態(tài)代碼塊 (線程安全)

    見注釋

    package com.artisan.example.singleton;import com.artisan.anno.ThreadSafe;/*** 餓漢模式 單例的實例在類裝載的時候進行創(chuàng)建* * 因為是在類裝載的時候進行創(chuàng)建,可以確保線程安全* * * 餓漢模式需要注意的地方: 1.私有構(gòu)造函數(shù)中不要有太多的邏輯,否則初始化會慢 2.確保初始化的對象能夠被使用,否則造成資源浪費* * @author yangshangwei**/ @ThreadSafe public class SingletonHungerModel2 {// 私有構(gòu)造函數(shù)// 如果要保證一個類只能被初始化一次,首先要保證的是構(gòu)造函數(shù)是私有的,不允許外部類直接調(diào)用new方法private SingletonHungerModel2() {// 可以初始化一些資源等}// 注意: static的順序不要寫反了,否則會拋空指針。 static的加載順序是按順序執(zhí)行// static單例對象 靜態(tài)域private static SingletonHungerModel2 instance = null;// 靜態(tài)塊static {instance = new SingletonHungerModel2();}// public方法外部通過getInstance獲取public static SingletonHungerModel2 getInstance() {// 直接返回實例化后的對象return instance;}}

    餓漢模式的第三種寫法 靜態(tài)內(nèi)部類 (線程安全)

    package com.artisan.example.singleton;import com.artisan.anno.ThreadSafe;/*** 餓漢模式 單例的實例在類裝載的時候進行創(chuàng)建* * 使用靜態(tài)內(nèi)部類實現(xiàn)的單例模式-線程安全* * * 餓漢模式需要注意的地方: 1.私有構(gòu)造函數(shù)中不要有太多的邏輯,否則初始化會慢 2.確保初始化的對象能夠被使用,否則造成資源浪費* * @author yangshangwei**/ @ThreadSafe public class SingletonHungerModel3 {// 私有構(gòu)造函數(shù)// 如果要保證一個類只能被初始化一次,首先要保證的是構(gòu)造函數(shù)是私有的,不允許外部類直接調(diào)用new方法private SingletonHungerModel3() {// 可以初始化一些資源等}// 靜態(tài)工廠方法-獲取實例public static SingletonHungerModel3 getInstance() {// 直接返回實例化后的對象return InstanceHolder.INSTANCE;}// 用靜態(tài)內(nèi)部類創(chuàng)建單例對象 private 修飾private static class InstanceHolder {private static final SingletonHungerModel3 INSTANCE = new SingletonHungerModel3();}}

    注意事項

    • 從外部無法訪問靜態(tài)內(nèi)部類InstanceHolder (private修飾的),只有當調(diào)用Singleton.getInstance方法的時候,才能得到單例對象instance。
    • instance對象初始化的時機并不是在單例類Singleton被加載的時候,而是在調(diào)用getInstance方法,使得靜態(tài)內(nèi)部類InstanceHolder 被加載的時候。因此這種實現(xiàn)方式是利用classloader的加載機制來實現(xiàn)懶加載,并保證構(gòu)建單例的線程安全。

    小結(jié)

    小結(jié): 以上所提到的單例實現(xiàn)方式并不能算是完全安全的,這里的安全不僅指線程安全還有發(fā)布對象的安全。因為以上例子所實現(xiàn)的單例模式,我們都可以通過反射機制去獲取私有構(gòu)造器更改其訪問級別從而實例化多個不同的對象。

    那么如何防止利用反射構(gòu)建對象呢?這時我們就需要使用到內(nèi)部枚舉類了,因為JVM可以阻止反射獲取枚舉類的私有構(gòu)造方法。


    枚舉模式 推薦 ( 線程安全,防止反射構(gòu)建)

    package com.artisan.example.singleton;import lombok.Getter;public class SingletonEum {/*** 私有構(gòu)造函數(shù)*/private SingletonEum() {}/*** 靜態(tài)工廠方法-獲取實例** @return instance*/public static SingletonEum getInstance() {return Singleton.INSTANCE.getInstance();}/*** 由枚舉類創(chuàng)建單例對象*/@Getterprivate enum Singleton {INSTANCE;/*** 單例對象*/private SingletonEum instance;/*** JVM保證這個方法絕對只調(diào)用一次*/Singleton() {instance = new SingletonEum();}}}

    使用枚舉實現(xiàn)的單例模式,不但可以防止利用反射強行構(gòu)建單例對象,而且可以保證線程安全,并且可以在枚舉類對象被反序列化的時候,保證反序列的返回結(jié)果是同一對象。

    上面代碼中之所以使用內(nèi)部枚舉類的原因是為了讓這個單例對象可以懶加載,相當于是結(jié)合了靜態(tài)內(nèi)部類的實現(xiàn)思想。若不使用內(nèi)部枚舉類的話,單例對象就會在枚舉類被加載的時候被構(gòu)建。


    代碼

    https://github.com/yangshangwei/ConcurrencyMaster

    總結(jié)

    以上是生活随笔為你收集整理的并发编程-09安全发布对象+单例模式详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 激情综合五月婷婷 | 国产视频日韩 | 亚洲成人久久精品 | 欧美高清hd | 国产xx在线观看 | 久热最新 | 特级黄色一级片 | 精品少妇一区二区三区在线观看 | 中文不卡视频 | 一区二区啪啪啪 | 国产精品成久久久久三级 | 99欧美| 色91视频 | 日本熟妇毛耸耸xxxxxx | 国产白袜脚足j棉袜在线观看 | np视频| 国产精品夜夜夜爽张柏芝 | 女人久久| 国产精品腿扒开做爽爽爽挤奶网站 | 欧美黄色三级视频 | 日日干日日草 | 成人毛片网站 | 免费中文字幕日韩欧美 | www.久久伊人 | 黄色片网站免费看 | 久久国产精品一区 | kk视频在线观看 | 免费av在线网址 | 国产56页 | 亚洲乱码精品久久久久 | 一级毛片黄色 | 成年丰满熟妇午夜免费视频 | 亚洲福利专区 | 婷婷一区二区三区 | 国产精选在线 | 一起草最新网址 | 亚洲精品一区二区三区中文字幕 | 色丁香av| 国产尤物在线视频 | 911香蕉视频| 蜜桃av久久久亚洲精品 | 丁香六月啪啪 | 澳门一级黄色片 | 实拍女处破www免费看 | 男人午夜视频 | 天天干夜夜嗨 | 亚洲爱视频| 日产精品一区二区 | 成人在线精品 | 99欧美精品 | 丁香花激情网 | 久久这里只有精品9 | 成人理论影院 | 亚洲成在人 | 亚洲精品国产电影 | 午夜精品视频一区 | 91成人免费在线 | 韩国伦理在线 | 亚洲精品911 | 亚洲欧美激情一区二区三区 | 射射射综合网 | 欧美日韩久久 | 午夜做爰xxxⅹ性高湖视频美国 | 中文字幕精品在线视频 | 97国产精品人人爽人人做 | 97国产精品视频人人做人人爱 | 国产激情一区二区三区 | 亚洲天堂网站在线 | 精品无码一区二区三区 | 欧美啪啪网| 一区二区视频在线免费观看 | 天天干天天爱天天射 | 999福利视频 | av精选| 亚洲欧美v | 午夜写真片福利电影网 | 黄色片毛片 | 亚洲欧美电影 | 国产情侣一区二区三区 | 亚洲激情专区 | 在线观看涩涩视频 | 无码精品人妻一二三区红粉影视 | 在线精品亚洲欧美日韩国产 | 亚洲综合图片区 | 亚洲一区欧美一区 | 欧美日韩国产区 | 午夜毛片在线观看 | 北条麻妃一二三区 | 物业福利视频 | 美女啪啪网站 | 日韩免费观看一区二区 | 成年视频在线 | 毛片导航 | 国产精品久久久久久久一区二区 | 国产精品tv| 亚洲视频一区二区在线观看 | 免费黄色一级 | 亚洲24p| 成片免费观看视频大全 |