欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

java高并發(fā)系列-第4天:JMM相關(guān)的一些概念

JMM(java內(nèi)存模型),由于并發(fā)程序要比串行程序復(fù)雜很多,其中一個(gè)重要原因是并發(fā)程序中數(shù)據(jù)訪問(wèn)一致性安全性將會(huì)受到嚴(yán)重挑戰(zhàn)。如何保證一個(gè)線程可以看到正確的數(shù)據(jù)呢?這個(gè)問(wèn)題看起來(lái)很白癡。對(duì)于串行程序來(lái)說(shuō),根本就是小菜一碟,如果你讀取一個(gè)變量,這個(gè)變量的值是1,那么你讀取到的一定是1,就是這么簡(jiǎn)單的問(wèn)題在并行程序中居然變得復(fù)雜起來(lái)。事實(shí)上,如果不加控制地任由線程胡亂并行,即使原本是1的數(shù)值,你也可能讀到2。因此我們需要在深入了解并行機(jī)制的前提下,再定義一種規(guī)則,保證多個(gè)線程間可以有小弟,正確地協(xié)同工作。而JMM也就是為此而生的。

創(chuàng)新互聯(lián)主營(yíng)平江網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,成都App制作,平江h(huán)5微信小程序搭建,平江網(wǎng)站營(yíng)銷(xiāo)推廣歡迎平江等地區(qū)企業(yè)咨詢(xún)

JMM關(guān)鍵技術(shù)點(diǎn)都是圍繞著多線程的原子性、可見(jiàn)性、有序性來(lái)建立的。我們需要先了解這些概念。

原子性

原子性是指操作是不可分的,要么全部一起執(zhí)行,要么不執(zhí)行。在java中,其表現(xiàn)在對(duì)于共享變量的某些操作,是不可分的,必須連續(xù)的完成。比如a++,對(duì)于共享變量a的操作,實(shí)際上會(huì)執(zhí)行3個(gè)步驟:

1.讀取變量a的值,假如a=1
2.a的值+1,為2
3.將2值賦值給變量a,此時(shí)a的值應(yīng)該為2

這三個(gè)操作中任意一個(gè)操作,a的值如果被其他線程篡改了,那么都會(huì)出現(xiàn)我們不希望出現(xiàn)的結(jié)果。所以必須保證這3個(gè)操作是原子性的,在操作a++的過(guò)程中,其他線程不會(huì)改變a的值,如果在上面的過(guò)程中出現(xiàn)其他線程修改了a的值,在滿足原子性的原則下,上面的操作應(yīng)該失敗。

java中實(shí)現(xiàn)原子操作的方法大致有2種:鎖機(jī)制無(wú)鎖CAS機(jī)制,后面的章節(jié)中會(huì)有介紹。

可見(jiàn)性

可見(jiàn)性是指一個(gè)線程對(duì)共享變量的修改,對(duì)于另一個(gè)線程來(lái)說(shuō)是否是可以看到的。有些同學(xué)會(huì)說(shuō)修改同一個(gè)變量,那肯定是可以看到的,難道線程眼盲了?

為什么會(huì)出現(xiàn)這種問(wèn)題呢?

看一下java線程內(nèi)存模型:

java高并發(fā)系列 - 第4天:JMM相關(guān)的一些概念

  • 我們定義的所有變量都儲(chǔ)存在主內(nèi)存
  • 每個(gè)線程都有自己獨(dú)立的工作內(nèi)存,里面保存該線程使用到的變量的副本(主內(nèi)存中該變量的一份拷貝)
  • 線程對(duì)共享變量所有的操作都必須在自己的工作內(nèi)存中進(jìn)行,不能直接從主內(nèi)存中讀寫(xiě)(不能越級(jí))
  • 不同線程之間也無(wú)法直接訪問(wèn)其他線程的工作內(nèi)存中的變量,線程間變量值的傳遞需要通過(guò)主內(nèi)存來(lái)進(jìn)行。(同級(jí)不能相互訪問(wèn))

線程需要修改一個(gè)共享變量X,需要先把X從主內(nèi)存復(fù)制一份到線程的工作內(nèi)存,在自己的工作內(nèi)存中修改完畢之后,再?gòu)墓ぷ鲀?nèi)存中回寫(xiě)到主內(nèi)存。
如果線程對(duì)變量的操作沒(méi)有刷寫(xiě)回主內(nèi)存的話,僅僅改變了自己的工作內(nèi)存的變量的副本,那么對(duì)于其他線程來(lái)說(shuō)是不可見(jiàn)的。
而如果另一個(gè)變量沒(méi)有讀取主內(nèi)存中的新的值,而是使用舊的值的話,同樣的也可以列為不可見(jiàn)。

共享變量可見(jiàn)性的實(shí)現(xiàn)原理:

線程A對(duì)共享變量的修改要被線程B及時(shí)看到的話,需要進(jìn)過(guò)以下步驟:

1.線程A在自己的工作內(nèi)存中修改變量之后,需要將變量的值刷新到主內(nèi)存中
2.線程B要把主內(nèi)存中變量的值更新到工作內(nèi)存中

關(guān)于線程可見(jiàn)性的控制,可以使用volatile、synchronized來(lái)實(shí)現(xiàn),后面章節(jié)會(huì)有詳細(xì)介紹。

有序性

有序性指的是程序按照代碼的先后順序執(zhí)行。

為了性能優(yōu)化,編譯器和處理器會(huì)進(jìn)行指令沖排序,有時(shí)候會(huì)改變程序語(yǔ)句的先后順序,比如程序。

int a = 1;  //1
int b = 20; //2
int c = a + b; //3

編譯器優(yōu)化后可能變成

int b = 20;  //1
int a = 1; //2
int c = a + b; //3

上面這個(gè)例子中,編譯器調(diào)整了語(yǔ)句的順序,但是不影響程序的最終結(jié)果。

在單例模式的實(shí)現(xiàn)上有一種雙重檢驗(yàn)鎖定的方式,代碼如下:

public class Singleton {
  static Singleton instance;
  static Singleton getInstance(){
    if (instance == null) {
      synchronized(Singleton.class) {
        if (instance == null)
          instance = new Singleton();
        }
    }
    return instance;
  }
}

我們先看instance = new Singleton();

未被編譯器優(yōu)化的操作:

  1. 指令1:分配一款內(nèi)存M
  2. 指令2:在內(nèi)存M上初始化Singleton對(duì)象
  3. 指令3:將M的地址賦值給instance變量

編譯器優(yōu)化后的操作指令:

  1. 指令1:分配一塊內(nèi)存S
  2. 指令2:將M的地址賦值給instance變量
  3. 指令3:在內(nèi)存M上初始化Singleton對(duì)象

現(xiàn)在有2個(gè)線程,剛好執(zhí)行的代碼被編譯器優(yōu)化過(guò),過(guò)程如下:

java高并發(fā)系列 - 第4天:JMM相關(guān)的一些概念

最終線程B獲取的instance是沒(méi)有初始化的,此時(shí)去使用instance可能會(huì)產(chǎn)生一些意想不到的錯(cuò)誤。

現(xiàn)在比較好的做法就是采用靜態(tài)內(nèi)部?jī)?nèi)的方式實(shí)現(xiàn):

public class SingletonDemo {
    private SingletonDemo() {
    }
    private static class SingletonDemoHandler{
        private static SingletonDemo instance = new SingletonDemo();
    }
    public static SingletonDemo getInstance() {
        return SingletonDemoHandler.instance;
    }
}


當(dāng)前標(biāo)題:java高并發(fā)系列-第4天:JMM相關(guān)的一些概念
路徑分享:http://chinadenli.net/article44/ihgeee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站網(wǎng)站設(shè)計(jì)、微信公眾號(hào)虛擬主機(jī)、網(wǎng)頁(yè)設(shè)計(jì)公司App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司