国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

這篇具有很好參考價(jià)值的文章主要介紹了Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

單例模式是經(jīng)典的設(shè)計(jì)模式之一。什么是設(shè)計(jì)模式?代碼的設(shè)計(jì)模式類(lèi)似于棋譜,棋譜就是一些下棋的固定套路,是前人總結(jié)出來(lái)的一些固定的打法。依照棋譜來(lái)下棋,不說(shuō)能下得非常好,但至少是有跡可循,不會(huì)下得很糟糕。代碼的設(shè)計(jì)模式也是一樣。

設(shè)計(jì)模式,就是軟件開(kāi)發(fā)中的棋譜。一些編程界的大佬,針對(duì)一些常見(jiàn)情景總結(jié)出了一些代碼的“編寫(xiě)套路”。按照這樣的套路來(lái)寫(xiě)代碼,不說(shuō)能寫(xiě)得非常好,但也至少不會(huì)寫(xiě)得太糟糕。以前有一個(gè)大佬寫(xiě)了一本書(shū),名叫《討論二十三種設(shè)計(jì)模式》,這本書(shū)廣為流傳,這里的設(shè)計(jì)模式也就是我們上面說(shuō)到的。

事實(shí)上設(shè)計(jì)模式遠(yuǎn)不止“二十三種”。以下兩種設(shè)計(jì)模式經(jīng)常遇到:

  1. 單例模式
  2. 工廠(chǎng)模式

本文主要介紹單例模式。

目錄

一、什么是單例模式?

二、如何實(shí)現(xiàn)單例模式?

1、代碼實(shí)現(xiàn):餓漢模式

a.餓漢模式的構(gòu)造思路

b.總結(jié):餓漢模式代碼

2、代碼實(shí)現(xiàn):懶漢模式

三、線(xiàn)程安全問(wèn)題

1、懶漢模式--線(xiàn)程不安全,餓漢模式--線(xiàn)程安全

2、初步解決:懶漢模式的線(xiàn)程安全問(wèn)題

3、代碼問(wèn)題-1:加鎖導(dǎo)致程序效率低——解決:更改加鎖的位置

4、代碼問(wèn)題-2:new操作引發(fā)指令重排序——解決:以volatile修飾

四、***小結(jié):?jiǎn)卫J降木€(xiàn)程安全問(wèn)題


一、什么是單例模式?

單例指的就是單個(gè)實(shí)例(instance),也就是單個(gè)對(duì)象(對(duì)象就是類(lèi)的實(shí)例)。單例模式指的是某個(gè)類(lèi)在進(jìn)程中只有唯一一個(gè)實(shí)例(在一個(gè)程序中,只能創(chuàng)建一個(gè)實(shí)例(一個(gè)對(duì)象),不能創(chuàng)建多個(gè)對(duì)象)。

按理來(lái)說(shuō),在寫(xiě)代碼的時(shí)候多 new 幾次,就能創(chuàng)建多個(gè)對(duì)象了。但在語(yǔ)法上,是有辦法禁止這樣多 new 幾次的操作的。?

也就是說(shuō),Java中的單例模式,實(shí)際上是借助 Java 語(yǔ)法,保證某個(gè)類(lèi)只能夠創(chuàng)建出一個(gè)實(shí)例,而不能被new多次。

為什么會(huì)有這樣的用途?其實(shí)原因是很簡(jiǎn)單的:在有些場(chǎng)景下,本身它就要求某個(gè)概念是單例的。比如每個(gè)人只能同時(shí)擁有一個(gè)配偶。


二、如何實(shí)現(xiàn)單例模式?

Java實(shí)現(xiàn)單例模式的方式有很多種,這里我們主要介紹兩種寫(xiě)法:

  1. 餓漢模式(急迫)
  2. 懶漢模式(從容)

如何理解?餓漢模式?和?懶漢模式?呢?餓漢模式就好比每次吃完飯之后,立刻就把碗給洗了(主打的就是一個(gè)急迫);懶漢模式則是每次吃完飯了,先把碗放到一邊先不洗,等到吃下一頓了再洗。通常認(rèn)為,懶漢模式更好,效率更高(非必要不洗碗)。

比如,中午吃飯用了4個(gè)碗,那么餓漢模式就得一次性把4個(gè)碗都洗了;而晚上吃飯要用2個(gè)碗,懶漢模式就只需要洗4個(gè)碗當(dāng)中用不到的2個(gè)碗就行了。洗2個(gè)碗明顯要比洗4個(gè)碗效率更高(不考慮沒(méi)洗的碗會(huì)變臭~(yú)~只考慮效率)。

在計(jì)算機(jī)中的例子:打開(kāi)一個(gè)硬盤(pán)上的文件,讀取文件內(nèi)容并顯示出來(lái)。

  • 餓漢:把文件所有內(nèi)容都讀到內(nèi)存中,并顯示。
  • 懶漢:只把文件讀一小部分,把當(dāng)前屏幕填充上。如果用戶(hù)翻頁(yè)了,再讀其它文件內(nèi)容;如果不翻頁(yè),就省下了。

在這樣的情況下,懶漢模式也是完勝餓漢模式的。

假設(shè)要讀取的文件非常大,有 10G,按照餓漢模式的方式,文件打開(kāi)可能都要卡半天,更何況還有內(nèi)存是否足夠的問(wèn)題。

但懶漢模式下就可以很快速地打開(kāi),因?yàn)樗蛔x取 1 頁(yè)的內(nèi)容,1 頁(yè)也就幾百字,可能也就讀取 2k 就夠了;如果用戶(hù)還要讀其它頁(yè)的內(nèi)容,懶漢再?gòu)膬?nèi)存里讀取相應(yīng)的內(nèi)容,用戶(hù)瀏覽不到的頁(yè)面,也就不將它的內(nèi)容加載到內(nèi)存中了。

(雖然懶漢模式會(huì)增加硬盤(pán)的讀取次數(shù),但和餓漢模式的情況相比,是不值一提的。)

下面我們來(lái)看看如何用代碼實(shí)現(xiàn)這兩種單例模式。

1、代碼實(shí)現(xiàn):餓漢模式

a.餓漢模式的構(gòu)造思路

我們先初步地創(chuàng)建出?Singleton 類(lèi),并在里面把對(duì)象創(chuàng)建出來(lái):

// 把一個(gè)類(lèi)設(shè)置成單例的
class Singleton {
    // 唯一實(shí)例的本體
    private static Singleton instance = new Singleton();    // 把對(duì)象創(chuàng)建出來(lái)

    // 獲取到實(shí)例的方法
    public static Singleton getInstance() {
        return instance;
    }
}

注意:這里的 instance 屬性要用 static 修飾,static變量保存了單例對(duì)象的唯一實(shí)例。

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

同時(shí),將 instance 屬性用private封裝,并提供一個(gè)get方法。這樣,我們就可以從外部獲取instance了:

public class Test {
    public static void main(String[] args) {
        // 此時(shí) s1 和 s2 是同一個(gè)對(duì)象
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();

    }
}

顯然,此處的 s1 和 s2 獲取到的實(shí)際是同一個(gè)對(duì)象。

但是,上述的代碼并沒(méi)有限定再次 new 對(duì)象的操作:

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

此處的 s3 也顯然與 s1 和 s2 不是同一個(gè)對(duì)象。因此,此處必須把 new 操作給禁止掉。采用的方式是 構(gòu)造方法私有化。

將構(gòu)造方法用 private 修飾,可以發(fā)現(xiàn),此時(shí)我們上面的 new 操作就報(bào)錯(cuò)了,無(wú)法通過(guò)編譯。

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

有些同學(xué)可能會(huì)想到,用反射仍然可以獲取到私有方法。一方面,反射本身就是一種非常規(guī)的手段,它本身就是不安全的;另一方面,單例模式有一種實(shí)現(xiàn)方式,借助枚舉,也可以保證反射下的安全,這個(gè)在此不過(guò)多介紹。

b.總結(jié):餓漢模式代碼

class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }

    private Singleton(){ }
}
public class Test {
    public static void main(String[] args) {
        //此時(shí)s1和s2是同一個(gè)對(duì)象
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
    }
}
Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題
將一個(gè)類(lèi)設(shè)置成單例的

通過(guò)Java語(yǔ)法來(lái)限制類(lèi)實(shí)例的多次創(chuàng)建,從而實(shí)現(xiàn)單例模式:

  1. static是用于類(lèi)級(jí)別的數(shù)據(jù)共享,保存了單例對(duì)象的唯一實(shí)例,可以在單例模式中用來(lái)單例實(shí)例的唯一性。
  2. 單例模式中將構(gòu)造方法私有化,可以避免外部直接創(chuàng)建新的實(shí)例。

但餓漢模式的有一個(gè)問(wèn)題,那就是實(shí)例的創(chuàng)建時(shí)機(jī)過(guò)早了。只要類(lèi)一加載,就會(huì)創(chuàng)建出這個(gè)實(shí)例,可要是后面并沒(méi)有用到這個(gè)實(shí)例呢?

更好的實(shí)現(xiàn)方式是懶漢模式。

2、代碼實(shí)現(xiàn):懶漢模式

懶漢模式的核心思想:非必要,不創(chuàng)建。懶漢模式和餓漢模式的代碼實(shí)現(xiàn)類(lèi)似,最大的區(qū)別是餓漢模式在不使用instance對(duì)象時(shí),不把它new出來(lái)。

以下代碼就是懶漢模式的實(shí)現(xiàn):

class SingletonLazy {
    //先令instance引用為null
    private static SingletonLazy instance = null;

    //獲取instance實(shí)例
    public static SingletonLazy getInstance() {
        if(instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }

    //構(gòu)造方法私有化
    private SingletonLazy() { }
}

????

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題
s1和s2是同一個(gè)實(shí)例

三、線(xiàn)程安全問(wèn)題

1、懶漢模式--線(xiàn)程不安全,餓漢模式--線(xiàn)程安全

在Java多線(xiàn)程編程中,非常重要的一個(gè)問(wèn)題就是線(xiàn)程安全問(wèn)題。上述提到的兩個(gè)代碼,是線(xiàn)程安全的嗎?即,多個(gè)線(xiàn)程下調(diào)用getInstance()是否會(huì)出現(xiàn)問(wèn)題?

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

結(jié)論是:餓漢模式是線(xiàn)程安全的,而懶漢模式不是線(xiàn)程安全的。?

比對(duì)線(xiàn)程不安全的原因:線(xiàn)程安全問(wèn)題及解決措施?

  1. 線(xiàn)程的搶占式執(zhí)行。
  2. 多個(gè)線(xiàn)程修改同一變量。
  3. 修改操作不是原子的。
  4. 內(nèi)存可見(jiàn)性問(wèn)題。
  5. 指令重排序。

這里,引起懶漢模式線(xiàn)程不安全的最直接原因,是多個(gè)線(xiàn)程修改同一變量。

在餓漢模式的getInstance()中,只是單純地讀操作(return),不涉及修改。而懶漢模式的getInstance()中有一個(gè)這樣的操作:先判定是否為null,再進(jìn)行修改,再返回。

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

很明顯,這里包含了修改的操作。上面的懶漢模式代碼在多線(xiàn)程下,可能無(wú)法保證創(chuàng)建對(duì)象的唯一性。如下圖情況中,t1和t2都會(huì)執(zhí)行到對(duì)象創(chuàng)建的代碼,從而創(chuàng)建出多份對(duì)象。

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

多創(chuàng)建一個(gè)對(duì)象,聽(tīng)起來(lái)似乎問(wèn)題不大,其實(shí)不然。對(duì)象是有大有小的,有些對(duì)象管理的內(nèi)存數(shù)據(jù)可能會(huì)很多,甚至可能多達(dá)幾百G。如果n個(gè)線(xiàn)程一起調(diào)用,創(chuàng)建出了n個(gè)這樣大的對(duì)象,后果是非常嚴(yán)重的。?

2、初步解決:懶漢模式的線(xiàn)程安全問(wèn)題

深入來(lái)說(shuō),引起上述問(wèn)題的原因是if判定操作修改操作不是原子的。可以通過(guò)加鎖來(lái)解決這個(gè)問(wèn)題。

但是,考慮到多線(xiàn)程代碼的復(fù)雜性,不是在代碼中任意寫(xiě)個(gè)加鎖,就一定線(xiàn)程安全了。如下面代碼所示:將synchronized加在了new對(duì)象的操作上,且以類(lèi)對(duì)象作為鎖對(duì)象。這樣的加鎖方式是不可行的,因?yàn)樵a出現(xiàn)線(xiàn)程不安全原因就是因?yàn)閕f判定操作與new操作不是原子的,而只把鎖加載new操作上,并不能保證if判定操作和修改操作整體的原子性。

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

因此,應(yīng)該把if操作也放到鎖里,才能保證判定和new是一個(gè)原子操作。

    //獲取instance實(shí)例
    public static SingletonLazy getInstance() {
        synchronized (SingletonLazy.class) {
            if (instance == null) {
                instance = new SingletonLazy();
            }
        }
        return instance;
    }

當(dāng)然,也可以直接將鎖加在方法上,直接保證整個(gè)方法都是原子的。

    //獲取instance實(shí)例
    synchronized public static SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }

3、代碼問(wèn)題-1:加鎖導(dǎo)致程序效率低——解決:更改加鎖的位置

在之前線(xiàn)程安全的篇章中提到過(guò),加鎖其實(shí)是一種非常低效的方式,因?yàn)榧渔i意味著會(huì)出現(xiàn)阻塞等待。事實(shí)上,應(yīng)該“非必要,不加鎖”。而我們上述的加鎖方式中存在一個(gè)問(wèn)題:不管什么時(shí)候調(diào)用getInstance(),都會(huì)觸發(fā)鎖的競(jìng)爭(zhēng)。?

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

然而其實(shí),此處的線(xiàn)程不安全只發(fā)生在首次創(chuàng)建對(duì)象這里。一旦對(duì)象new好了,后續(xù)再調(diào)用getInstance(),就是單純的讀操作,就沒(méi)有線(xiàn)程安全問(wèn)題了,也就沒(méi)必要再加鎖了。

怎么優(yōu)化呢?我們就需要針對(duì)加鎖再做一次判定:

什么時(shí)候需要加鎖?——對(duì)象為空的時(shí)候。?

因此,要再加一層if判斷,用于判斷需要加鎖的情況:

    //獲取instance實(shí)例
    public static SingletonLazy getInstance() {
        // 這個(gè)條件用于判斷是否要加鎖
        // 如果對(duì)象已經(jīng)有了,就不必加鎖了,此時(shí)本身就是線(xiàn)程安全的
        if(instance == null) {
            synchronized (SingletonLazy.class) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }

?注意這兩個(gè)if(instance == null)代碼的辨析:

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

并且,雖然這倆代碼是挨著的,但是實(shí)際上它們執(zhí)行的時(shí)機(jī)差別會(huì)很大。?

按照我們?cè)趩尉€(xiàn)程代碼中的理解,如果兩行代碼緊挨著,那么執(zhí)行的時(shí)候,這兩行代碼會(huì)被迅速執(zhí)行完,可以近似地看作它們是同一時(shí)機(jī)被執(zhí)行。

但是,在多線(xiàn)程且上述兩個(gè)if判斷間隔著一層synchronized加鎖的情況下,就不能簡(jiǎn)單地這樣理解了。

加鎖就可能導(dǎo)致線(xiàn)程阻塞,而等到線(xiàn)程阻塞被接觸時(shí),可能早已是“滄海桑田”。換句話(huà)說(shuō),這兩行代碼雖然看起來(lái)是相鄰的,但它們執(zhí)行的時(shí)間間隔可能會(huì)非常長(zhǎng)。雖然兩個(gè)條件代碼完全相同,但若調(diào)用的時(shí)間間隔長(zhǎng)了,判斷結(jié)果也可能會(huì)不同。

比如在一個(gè)線(xiàn)程執(zhí)行時(shí),剛開(kāi)始instance為null,第一個(gè)if判定成立,進(jìn)入外層if;接下來(lái)獲取鎖時(shí)卻發(fā)現(xiàn),鎖已經(jīng)被別的線(xiàn)程獲取了,那么這個(gè)線(xiàn)程此時(shí)就只能阻塞等待;等到這個(gè)線(xiàn)程結(jié)束阻塞、再往下走的時(shí)候,instance卻已經(jīng)被別的線(xiàn)程創(chuàng)建好了,不再為null,那么第二個(gè)條件判定就不成立了;該線(xiàn)程不會(huì)進(jìn)入第二層if,也就不會(huì)重復(fù)再new一個(gè)對(duì)象了。

4、代碼問(wèn)題-2:new操作引發(fā)指令重排序——解決:以volatile修飾

在之前線(xiàn)程安全的篇章中提到過(guò),指令重排序也可能導(dǎo)致線(xiàn)程不安全。new操作包括3個(gè)步驟:1、創(chuàng)建內(nèi)存;2、調(diào)用構(gòu)造方法;3、把地址賦值給引用。這其中就可能存在指令重排序:步驟2和步驟3的順序可以調(diào)換。

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

如果程序按照 1-3-2 的方式執(zhí)行new操作,就可能出現(xiàn)問(wèn)題:

若instance為null,當(dāng)t1線(xiàn)程執(zhí)行完1和3這兩個(gè)步驟后,線(xiàn)程突然被調(diào)度到t2;t2再去判定條件,但由于在t1中instance已經(jīng)獲取了內(nèi)存地址,因此instance非null,條件不成立,會(huì)直接返回實(shí)例的引用。此時(shí),t2拿到的是一個(gè)沒(méi)裝修過(guò)的毛坯房。

如果接下來(lái)t2繼續(xù)毛坯房的后續(xù)方法,可能都是將錯(cuò)就錯(cuò)了。

Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題

總而言之,這樣的線(xiàn)程調(diào)度時(shí)機(jī),可能導(dǎo)致t2拿到的實(shí)例是不完整的,從而就出現(xiàn)問(wèn)題了。雖然這個(gè)過(guò)程是一個(gè)極端小概率的情況,但在服務(wù)器高并發(fā)、大數(shù)據(jù)的情況下,一旦出問(wèn)題,后果仍然是非常嚴(yán)重的。

如何解決這個(gè)問(wèn)題?很簡(jiǎn)單,將instance加上volatile即可。volatile可以禁止指令重排序。

    //加上volatile
    volatile private static SingletonLazy instance = null;

    //獲取instance實(shí)例
    public static SingletonLazy getInstance() {
        // 這個(gè)條件用于判斷是否要加鎖
        // 如果對(duì)象已經(jīng)有了,就不必加鎖了,此時(shí)本身就是線(xiàn)程安全的
        if(instance == null) {
            synchronized (SingletonLazy.class) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }

補(bǔ)充:這里是否涉及到內(nèi)存可見(jiàn)性問(wèn)題是存疑的。內(nèi)存可見(jiàn)性問(wèn)題的發(fā)生是由于編譯器優(yōu)化掉了寄存器從內(nèi)存中l(wèi)oad的這一操作,從而使得每一次讀取數(shù)據(jù)的時(shí)并沒(méi)有真正從內(nèi)存中讀取,而是只從寄存器中讀取。在一個(gè)線(xiàn)程頻繁寫(xiě),一個(gè)線(xiàn)程頻繁讀的情況下,可能會(huì)出現(xiàn)內(nèi)存可見(jiàn)性的問(wèn)題。但是,上述代碼是否涉及“頻繁讀”?假設(shè)N個(gè)線(xiàn)程一起調(diào)用,是否就相當(dāng)于讀了N次,這樣不就會(huì)觸發(fā)編譯器的優(yōu)化操作?

這其實(shí)是不一定的。因?yàn)槊恳粋€(gè)線(xiàn)程,會(huì)有自己的一套寄存器,這其中是否會(huì)出現(xiàn)內(nèi)存安全性問(wèn)題,是很難確定的。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-454642.html


四、***小結(jié):?jiǎn)卫J降木€(xiàn)程安全問(wèn)題

  • 餓漢模式:天然就是安全的,只是讀操作。
  • 懶漢模式:不安全的有讀操作,也有寫(xiě)操作。如何保證懶漢模式的線(xiàn)程安全問(wèn)題:
    1. 加鎖,把 if 和 new 變成原子操作。
    2. 雙重 if,減少不必要的加鎖操作。
    3. 使用 volatile 禁止指重排序,保證后續(xù)線(xiàn)程肯定拿到的是完整對(duì)象。

到了這里,關(guān)于Java多線(xiàn)程基礎(chǔ)-8:?jiǎn)卫J郊捌渚€(xiàn)程安全問(wèn)題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Java 枚舉實(shí)現(xiàn)單例模式,線(xiàn)程安全又優(yōu)雅!

    Java 枚舉實(shí)現(xiàn)單例模式,線(xiàn)程安全又優(yōu)雅!

    這種DCL寫(xiě)法的優(yōu)點(diǎn):不僅線(xiàn)程安全,而且延遲加載。 1.1 為什么要double check?去掉第二次check行不行? 當(dāng)然不行,當(dāng)2個(gè)線(xiàn)程同時(shí)執(zhí)行g(shù)etInstance方法時(shí),都會(huì)執(zhí)行第一個(gè)if判斷,由于鎖機(jī)制的存在,會(huì)有一個(gè)線(xiàn)程先進(jìn)入同步語(yǔ)句,而另一個(gè)線(xiàn)程等待,當(dāng)?shù)谝粋€(gè)線(xiàn)程執(zhí)行了 new Sin

    2024年02月02日
    瀏覽(20)
  • 【Java中23種設(shè)計(jì)模式-單例模式2--懶漢式2線(xiàn)程安全】

    【Java中23種設(shè)計(jì)模式-單例模式2--懶漢式2線(xiàn)程安全】

    加油,新時(shí)代打工人! 簡(jiǎn)單粗暴,學(xué)習(xí)Java設(shè)計(jì)模式。 23種設(shè)計(jì)模式定義介紹 Java中23種設(shè)計(jì)模式-單例模式 Java中23種設(shè)計(jì)模式-單例模式2–懶漢式線(xiàn)程不安全 通過(guò)運(yùn)行結(jié)果看,兩個(gè)線(xiàn)程的地址值是相同的,說(shuō)明內(nèi)存空間里,創(chuàng)建了一個(gè)對(duì)象。

    2024年02月20日
    瀏覽(29)
  • 【Linux】線(xiàn)程池設(shè)計(jì)/單例模式/STL、智能指針與線(xiàn)程安全/讀者寫(xiě)者問(wèn)題

    線(xiàn)程池:一種線(xiàn)程使用模式。線(xiàn)程過(guò)多會(huì)帶來(lái)調(diào)度開(kāi)銷(xiāo),進(jìn)而影響緩存局部性和整體性能。而線(xiàn)程池維護(hù)著多個(gè)線(xiàn)程,等待著監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù)。這避免了在處理短時(shí)間任務(wù)時(shí)創(chuàng)建與銷(xiāo)毀線(xiàn)程的代價(jià)。線(xiàn)程池不僅能夠保證內(nèi)核的充分利用,還能防止過(guò)分調(diào)度。可

    2024年02月03日
    瀏覽(21)
  • 【liunx】線(xiàn)程池+單例模式+STL,智能指針和線(xiàn)程安全+其他常見(jiàn)的各種鎖+讀者寫(xiě)者問(wèn)題

    【liunx】線(xiàn)程池+單例模式+STL,智能指針和線(xiàn)程安全+其他常見(jiàn)的各種鎖+讀者寫(xiě)者問(wèn)題

    喜歡的點(diǎn)贊,收藏,關(guān)注一下把! 目前我們學(xué)了掛起等待鎖、條件變量、信號(hào)量、生產(chǎn)者消費(fèi)者模型那我們就根據(jù)這些寫(xiě)一個(gè)線(xiàn)程池! 線(xiàn)程池: 一種線(xiàn)程使用模式。線(xiàn)程過(guò)多會(huì)帶來(lái)調(diào)度開(kāi)銷(xiāo),進(jìn)而影響緩存局部性和整體性能。而線(xiàn)程池維護(hù)著多個(gè)線(xiàn)程,等待著監(jiān)督管理者分配

    2024年02月02日
    瀏覽(26)
  • 【多線(xiàn)程】線(xiàn)程安全的單例模式

    【多線(xiàn)程】線(xiàn)程安全的單例模式

    單例模式能保證某個(gè)類(lèi)在程序中只存在 唯一 一份實(shí)例, 而不會(huì)創(chuàng)建出多個(gè)實(shí)例,從而節(jié)約了資源并實(shí)現(xiàn)數(shù)據(jù)共享。 比如 JDBC 中的 DataSource 實(shí)例就只需要一個(gè). 單例模式具體的實(shí)現(xiàn)方式, 分成 “餓漢” 和 “懶漢” 兩種. 類(lèi)加載的同時(shí), 創(chuàng)建實(shí)例. 注意: 使用 static 修飾 instanc

    2024年02月09日
    瀏覽(18)
  • 線(xiàn)程安全之單例模式

    線(xiàn)程安全之單例模式

    這篇文章,我們會(huì)介紹一下單例模式,但這里的單例模式,不是我們所說(shuō)的設(shè)計(jì)模式,當(dāng)然聽(tīng)到設(shè)計(jì)模式,大家一定都說(shuō),我當(dāng)然知道設(shè)計(jì)模式了,有23種呢?一下子一頓輸出,當(dāng)然我這里說(shuō)的單例模式還是跟設(shè)計(jì)模式有一些區(qū)別的,當(dāng)然我不做概述,因?yàn)槲乙矝](méi)咋個(gè)去了解過(guò)設(shè)計(jì)模式,我把

    2024年02月06日
    瀏覽(20)
  • 單例模式的線(xiàn)程安全形式

    目錄 1.單例設(shè)計(jì)模式的概念 2.實(shí)現(xiàn)方法: 1.餓漢式 2.懶漢式 3.區(qū)分餓漢式和懶漢式: 3.單例模式的雙重校驗(yàn)線(xiàn)程安全形式 1.線(xiàn)程安全問(wèn)題的解決方法 1.1 synchronized: 1.2 volatile: ????????保證變量可見(jiàn)性(不保證原子性) ? ? ? ? 禁止指令的重排序 2.線(xiàn)程安全

    2024年02月15日
    瀏覽(13)
  • 設(shè)計(jì)模式3:?jiǎn)卫J剑红o態(tài)內(nèi)部類(lèi)模式是怎么保證單例且線(xiàn)程安全的?

    設(shè)計(jì)模式3:?jiǎn)卫J剑红o態(tài)內(nèi)部類(lèi)模式是怎么保證單例且線(xiàn)程安全的?

    上篇文章:設(shè)計(jì)模式3:?jiǎn)卫J剑红o態(tài)內(nèi)部類(lèi)單例模式簡(jiǎn)單測(cè)試了靜態(tài)內(nèi)部類(lèi)單例模式,確實(shí)只生成了一個(gè)實(shí)例。我們繼續(xù)深入理解。 靜態(tài)變量什么時(shí)候被初始化? 這行代碼 private static Manager instance = new Manager(); 什么時(shí)候執(zhí)行? 編譯期間將.java文件轉(zhuǎn)為.class文件,運(yùn)行期間

    2024年02月12日
    瀏覽(16)
  • 【并發(fā)專(zhuān)題】單例模式的線(xiàn)程安全(進(jìn)階理解篇)

    【并發(fā)專(zhuān)題】單例模式的線(xiàn)程安全(進(jìn)階理解篇)

    最近學(xué)習(xí)了JVM之后,總感覺(jué)知識(shí)掌握不夠深,所以想通過(guò)分析經(jīng)典的【懶漢式單例】來(lái)加深一下理解。(主要是【靜態(tài)內(nèi)部類(lèi)】實(shí)現(xiàn)單例的方式)。 如果小白想理解單例的話(huà),也能看我這篇文章。我也通過(guò)了【前置知識(shí)】跟【普通懶漢式】、【雙檢鎖懶漢】、【靜態(tài)內(nèi)部類(lèi)】

    2024年02月14日
    瀏覽(20)
  • java基礎(chǔ)之線(xiàn)程安全問(wèn)題以及線(xiàn)程安全集合類(lèi)

    當(dāng)多個(gè)線(xiàn)程同時(shí)訪(fǎng)問(wèn)同一個(gè)臨界資源時(shí),原子操作可能被破壞,會(huì)導(dǎo)致數(shù)據(jù)丟失, 就會(huì)觸發(fā)線(xiàn)程安全問(wèn)題 臨界資源: 被多個(gè)線(xiàn)程同時(shí)訪(fǎng)問(wèn)的對(duì)象 原子操作: 線(xiàn)程訪(fǎng)問(wèn)臨界資源的過(guò)程中不可更改和缺失的操作 互斥鎖 每個(gè)對(duì)象都默認(rèn)擁有互斥鎖, 該鎖默認(rèn)不開(kāi)啟. 當(dāng)開(kāi)啟互斥鎖之后

    2024年01月18日
    瀏覽(66)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包