Java并發(fā)編程 -- 單例模式線程安全問題

單例模式是指對(duì)一個(gè)對(duì)象進(jìn)行一次實(shí)例化,然后全局都可以調(diào)用該實(shí)例化對(duì)象來完成項(xiàng)目的開發(fā)。

在計(jì)算機(jī)系統(tǒng)中,線程池、緩存、日志對(duì)象、對(duì)話框、打印機(jī)、顯卡的驅(qū)動(dòng)程序?qū)ο蟪1辉O(shè)計(jì)成單例。這些應(yīng)用都或多或少具有資源管理器的功能。每臺(tái)計(jì)算機(jī)可以有若干個(gè)打印機(jī),但只能有一個(gè)Printer Spooler,以避免兩個(gè)打印作業(yè)同時(shí)輸出到打印機(jī)中。每臺(tái)計(jì)算機(jī)可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口,以避免一個(gè)通信端口同時(shí)被兩個(gè)請(qǐng)求同時(shí)調(diào)用??傊?,選擇單例模式就是為了避免不一致狀態(tài),避免政出多頭。

實(shí)現(xiàn)單例的不同方式

餓漢式單例

餓漢式單例是指在方法調(diào)用前,實(shí)例就已經(jīng)創(chuàng)建好了。下面是實(shí)現(xiàn)代碼:

package com.thread.singleton;

/**
 * 單例模式-- 餓漢式
 * Created by Fant.J.
 * 2018/2/25 19:24
 */
public class Singleton1 {
    /** 私有化構(gòu)造方法,在外部不能實(shí)例化對(duì)象 */
    private Singleton1(){}

    /** 在這里實(shí)例化 靜態(tài)對(duì)象  (優(yōu)點(diǎn):不存在線程安全問題。  缺點(diǎn):每次調(diào)用都實(shí)例化,占用空間) */
    private static Singleton1 singleton1 = new Singleton1();

    public static Singleton1 getInstance(){
        return singleton1;
    }

}

優(yōu)點(diǎn):不存在線程安全問題。 缺點(diǎn):每次調(diào)用都實(shí)例化,占用空間

懶漢式單例

懶漢式單例是指在方法調(diào)用獲取實(shí)例時(shí)才創(chuàng)建實(shí)例,因?yàn)橄鄬?duì)餓漢式顯得“不急迫”,所以被叫做“懶漢模式”。下面是實(shí)現(xiàn)代碼:

package com.thread.singleton;

/**
 * 單例模式 -- 懶漢式
 * Created by Fant.J.
 * 2018/2/25 19:30
 */
public class Singleton2 {


    private Singleton2(){}

    private static Singleton2 instance;

    public synchronized static Singleton2 getInstance()  {
        /* 下面這段代碼  不是原子性操作  會(huì)出現(xiàn)線程安全問題 。**/
        if (instance == null) {
                    instance = new Singleton2();                            
        }
        return instance;
    }
}

在這段代碼中,在if語句里面,就可能跑有多個(gè)線程同步判斷和同步new。會(huì)產(chǎn)生線程安全問題。

解決方法:
  1. 給方法加上synchronized(變成單線程,影響性能)
  2. 給代碼塊加synchronized(雙重檢查加鎖)
    雖然2方法解決了性能問題, 但是還會(huì)有問題 。
    問題來自 jvm 的優(yōu)化:指令重排序(有興趣了解)
    我們可以在對(duì)象中添加volatile 關(guān)鍵字來 不讓jvm對(duì)該 對(duì)象做優(yōu)化
    完善后的代碼如下:
package com.thread.singleton;

/**
 * 單例模式 -- 懶漢式
 * Created by Fant.J.
 * 2018/2/25 19:30
 */
public class Singleton2 {


    private Singleton2(){}

    private static volatile Singleton2 instance;

    public synchronized static Singleton2 getInstance()  {
        /* 下面這段代碼  不是原子性操作  會(huì)出現(xiàn)線程安全問題 。
            解決方法:1.給方法加上synchronized(變成單線程,影響性能)
                    2.給代碼塊加synchronized(雙重檢查加鎖)
                      雖然2方法解決了性能問題,  但是還會(huì)有問題 。
                      問題來自  jvm 的優(yōu)化:指令重排序(有興趣了解)
                      我們可以在對(duì)象中添加volatile 關(guān)鍵字來 不讓jvm對(duì)該 對(duì)象做優(yōu)化
        **/
        if (instance == null) {
            synchronized (Singleton2.class){
                if (instance == null){
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,755評(píng)論 11 349
  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡(jiǎn)單、最易理解的設(shè)計(jì)模式,也因?yàn)樗暮?jiǎn)潔易懂,是項(xiàng)目中最...
    成熱了閱讀 4,530評(píng)論 4 34
  • 怎么形容這場(chǎng)雨才能讓你有身臨其境的感覺呢? 大概就是「漂洋過海來看你」吧。 從家到公司也就十五分鐘的路程,小腿以上...
    饅頭泡稀飯閱讀 515評(píng)論 0 0
  • (1)表白 唉。。。。。 如果你討厭我。。。 為什么還來招惹我。。。 蛤?我什么時(shí)候招惹你啦? emmm。。。逗我...
    中毒HDH閱讀 1,179評(píng)論 0 1
  • 有人說,人生是見天地,見眾生,見自己的過程。 我于是錯(cuò)誤的把重點(diǎn)放在了見自己上,我每天問自己,你今...
    晨樹御風(fēng)閱讀 425評(píng)論 0 0

友情鏈接更多精彩內(nèi)容