成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java 并發(fā)學(xué)習(xí)筆記(一)——原子性、可見性、有序性問題

Chao / 2620人閱讀

摘要:最后,總結(jié)一下,導(dǎo)致并發(fā)問題的三個(gè)源頭分別是原子性一個(gè)線程在執(zhí)行的過程當(dāng)中不被中斷??梢娦砸粋€(gè)線程修改了共享變量,另一個(gè)線程能夠馬上看到,就叫做可見性。

計(jì)算機(jī)的 CPU、內(nèi)存、I/O 設(shè)備的速度一直存在較大的差異,依次是 CPU > 內(nèi)存 > I/O 設(shè)備,為了權(quán)衡這三者的速度差異,主要提出了三種解決辦法:

CPU 增加了緩存,均衡和內(nèi)存的速度差異

發(fā)明了進(jìn)程、線程,分時(shí)復(fù)用 CPU,提高 CPU 的使用效率

編譯指令優(yōu)化,更好的利用緩存

三種解決辦法雖然有效,但是也帶來了另外的三個(gè)問題,分別就是并發(fā) bug 產(chǎn)生的源頭。

1.可見性問題

如果是單核 CPU,多個(gè)線程操作的都是同一個(gè) CPU 緩存,那么一個(gè)線程修改了共享變量,另一個(gè)線程肯定能馬上看到。

如果是多核 CPU ,每個(gè) CPU 都有自己的緩存,這樣線程對(duì)共享變量的修改便對(duì)其他線程不可見了。

2.原子性問題

為什么會(huì)有線程切換?一個(gè)線程在執(zhí)行的過程中,可能會(huì)進(jìn)行耗時(shí)的 I/O 操作,這時(shí)線程需要等待 I/O 操作完成。線程在等待的過程中,可以釋放 CPU 的使用權(quán),讓另一個(gè)線程執(zhí)行,這樣能夠提高 CPU 的使用率。

例如上圖,兩個(gè)線程同時(shí)對(duì)變量 count 加 1,線程 A 在執(zhí)行的過程中切換到了線程 B,最后導(dǎo)致寫入到內(nèi)存的值都是 1,與預(yù)期不符。

3.有序性問題

首先看一段很經(jīng)典的獲取單例對(duì)象的代碼:

public class Singleton {
    
    private static Singleton instance;
     //Java 獲取單例對(duì)象
    public Singleton getInstance(){
        if (instance == null){
            synchronized (Singleton.class){
                if (instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

程序的邏輯是:首先判斷 instance 是否為空,如果為空,對(duì)其加鎖,然后再判斷是否為空,此時(shí)為空的話則初始化 instance 對(duì)象。

如果線程 A 和 B 同時(shí)執(zhí)行方法,在 synchronized 處,一個(gè)線程會(huì)被阻塞,假設(shè)被阻塞的是線程 B,此時(shí)線程 A 進(jìn)入并初始化 instance,然后喚醒線程 B,線程 B 進(jìn)入的時(shí)候,發(fā)現(xiàn) instance 不為空了,所以不會(huì)創(chuàng)建對(duì)象。

但是因?yàn)橛行蛐詥栴}的存在,這段代碼也不是想象的那么完美,我們期望的初始化對(duì)象的過程是這樣的:1.分配內(nèi)存;2.初始化對(duì)象;3.將內(nèi)存地址賦給 instance。但是經(jīng)過編譯優(yōu)化之后,卻是這樣的:

1.分配內(nèi)存

2.將內(nèi)存地址賦給 instance

3.在內(nèi)存上面初始化對(duì)象

這樣,如果線程 A 執(zhí)行到了第二步,然后切換到 線程 B,線程 B 就會(huì)認(rèn)為 instance 不為空然后直接返回了,實(shí)際上 instance 并沒有初始化。

最后,總結(jié)一下,導(dǎo)致并發(fā)問題的三個(gè)源頭分別是

原子性:一個(gè)線程在執(zhí)行的過程當(dāng)中不被中斷。

可見性:一個(gè)線程修改了共享變量,另一個(gè)線程能夠馬上看到,就叫做可見性。

有序性:編譯指令重排導(dǎo)致的問題。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74507.html

相關(guān)文章

  • 多線程學(xué)習(xí)筆記(1):volatile和synchronized

    摘要:今天開始整理學(xué)習(xí)多線程的知識(shí),談?wù)勛钪匾膬蓚€(gè)關(guān)鍵字和。但是這樣一個(gè)過程比較慢,在使用多線程的時(shí)候就會(huì)出現(xiàn)問題。有序性有序性是指多線程執(zhí)行結(jié)果的正確性。這種機(jī)制在多線程中會(huì)出現(xiàn)問題,因此可以通過來禁止重排。 今天開始整理學(xué)習(xí)多線程的知識(shí),談?wù)勛钪匾膬蓚€(gè)關(guān)鍵字:volatile和synchronized。 一、三個(gè)特性 1、原子性 所謂原子性操作就是指這些操作是不可中斷的,要么執(zhí)行過程...

    jk_v1 評(píng)論0 收藏0
  • 來,了解Java內(nèi)存模型(JMM)

    摘要:因?yàn)楣芾砣藛T是了解手下的人員以及自己負(fù)責(zé)的事情的。處理器優(yōu)化和指令重排上面提到在在和主存之間增加緩存,在多線程場(chǎng)景下會(huì)存在緩存一致性問題。有沒有發(fā)現(xiàn),緩存一致性問題其實(shí)就是可見性問題。 網(wǎng)上有很多關(guān)于Java內(nèi)存模型的文章,在《深入理解Java虛擬機(jī)》和《Java并發(fā)編程的藝術(shù)》等書中也都有關(guān)于這個(gè)知識(shí)點(diǎn)的介紹。但是,很多人讀完之后還是搞不清楚,甚至有的人說自己更懵了。本文,就來整體的...

    kviccn 評(píng)論0 收藏0
  • 來,了解Java內(nèi)存模型(JMM)

    摘要:因?yàn)楣芾砣藛T是了解手下的人員以及自己負(fù)責(zé)的事情的。處理器優(yōu)化和指令重排上面提到在在和主存之間增加緩存,在多線程場(chǎng)景下會(huì)存在緩存一致性問題。有沒有發(fā)現(xiàn),緩存一致性問題其實(shí)就是可見性問題。 網(wǎng)上有很多關(guān)于Java內(nèi)存模型的文章,在《深入理解Java虛擬機(jī)》和《Java并發(fā)編程的藝術(shù)》等書中也都有關(guān)于這個(gè)知識(shí)點(diǎn)的介紹。但是,很多人讀完之后還是搞不清楚,甚至有的人說自己更懵了。本文,就來整體的...

    eccozhou 評(píng)論0 收藏0
  • Java并發(fā)】線程安全

    摘要:另一個(gè)是使用鎖的機(jī)制來處理線程之間的原子性。依賴于去實(shí)現(xiàn)鎖,因此在這個(gè)關(guān)鍵字作用對(duì)象的作用范圍內(nèi),都是同一時(shí)刻只能有一個(gè)線程對(duì)其進(jìn)行操作的。 線程安全性 定義:當(dāng)多個(gè)線程訪問某個(gè)類時(shí),不管運(yùn)行時(shí)環(huán)境采用何種調(diào)度方式或者這些線程將如何交替執(zhí)行,并且在主調(diào)代碼中不需要任何額外的同步或協(xié)同,這個(gè)類都能表現(xiàn)出正確的行為,那么就稱這個(gè)類是線程安全的。 線程安全性主要體現(xiàn)在三個(gè)方面:原子性、可見性...

    劉玉平 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<