国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java多線程基礎(chǔ)(二)——Java內(nèi)存模型

huhud / 1861人閱讀

摘要:一主存儲(chǔ)器與工作存儲(chǔ)器內(nèi)存模型分為主存儲(chǔ)器和工作存儲(chǔ)器兩種。工作存儲(chǔ)器每個(gè)線程各自獨(dú)立所擁有的作業(yè)區(qū),在中,存有中的部分拷貝,稱之為工作拷貝。注意線程欲退出時(shí),不會(huì)執(zhí)行工作存儲(chǔ)器的釋放操作。

一、主存儲(chǔ)器與工作存儲(chǔ)器

Java內(nèi)存模型(memory model)分為主存儲(chǔ)器(main memory)和工作存儲(chǔ)器(working memory)兩種。

主存儲(chǔ)器(main memory):
類的實(shí)例所存在的區(qū)域,main memory為所有的線程所共享。

工作存儲(chǔ)器(working memory):
每個(gè)線程各自獨(dú)立所擁有的作業(yè)區(qū),在working memory中,存有main memory中的部分拷貝,稱之為工作拷貝(working copy)。

二、字段的使用 2.1 字段的引用

線程無法直接對(duì)主存儲(chǔ)器進(jìn)行操作,當(dāng)線程需要引用實(shí)例的字段的值時(shí),會(huì)一次將字段值從主存儲(chǔ)器拷貝到工作存儲(chǔ)器上(相當(dāng)于上圖中的read->load)。
當(dāng)線程再次需要引用相同的字段時(shí),可能直接使用剛才的工作拷貝(use),也可能重新從主存儲(chǔ)器獲取(read->load->use)。
具體會(huì)出現(xiàn)哪種情況,由JVM決定。

2.2 字段的賦值

由于線程無法直接對(duì)主存儲(chǔ)器進(jìn)行操作,所以也就無法直接將值指定給字段。
當(dāng)線程欲將值指定給字段時(shí),會(huì)一次將值指定給位于工作存儲(chǔ)器上的工作拷貝(assign),指定完成后,工作拷貝的內(nèi)容便會(huì)復(fù)制到主存儲(chǔ)器(store->write),至于何時(shí)進(jìn)行復(fù)制,由JVM決定。
因此,當(dāng)線程反復(fù)對(duì)一個(gè)實(shí)例的字段進(jìn)行賦值時(shí),可能只會(huì)對(duì)工作拷貝進(jìn)行指定(assign),此時(shí)只有指定的最后結(jié)果會(huì)在某個(gè)時(shí)刻拷貝到主存儲(chǔ)器(store-write);也可能在每次指定時(shí),都進(jìn)行拷貝到主存儲(chǔ)器的操作(assign->store->write)。

三、線程的原子操作

Java語(yǔ)言規(guī)范定義了線程的六種原子操作:

read
負(fù)責(zé)從主存儲(chǔ)器(main memory)拷貝到工作存儲(chǔ)器(working memory)

write
與上述相反,負(fù)責(zé)從工作存儲(chǔ)器(working memory)拷貝到主存儲(chǔ)器(main memory)

use
表示線程引用工作存儲(chǔ)器(working memory)的值

assign
表示線程將值指定給工作存儲(chǔ)器(working memory)

lock
表示線程取得鎖定

unlock
表示線程解除鎖定

四、synchronied的本質(zhì) 4.1 線程欲進(jìn)入synchronized

線程欲進(jìn)入synchronized時(shí),會(huì)執(zhí)行以下兩類操作:

強(qiáng)制寫入主存儲(chǔ)器(main memory)

當(dāng)線程欲進(jìn)入synchronized時(shí),如果該線程的工作存儲(chǔ)器(working memory)上有未映像到主存儲(chǔ)器的拷貝,則這些內(nèi)容會(huì)強(qiáng)制寫入主存儲(chǔ)器(store->write),則這些計(jì)算結(jié)果就會(huì)對(duì)其它線程可見(visible)。

工作存儲(chǔ)器(working memory)的釋放

當(dāng)線程欲進(jìn)入synchronized時(shí),工作存儲(chǔ)器上的工作拷貝會(huì)被全部丟棄。之后,欲引用主存儲(chǔ)器上的值的線程,必定會(huì)從主存儲(chǔ)器將值拷貝到工作拷貝(read->load)。

4.2 線程欲退出synchronized

線程欲退出synchronized時(shí),會(huì)執(zhí)行以下操作:

強(qiáng)制寫入主存儲(chǔ)器(main memory)

當(dāng)線程欲退出synchronized時(shí),如果該線程的工作存儲(chǔ)器(working memory)上有未映像到主存儲(chǔ)器的拷貝,則這些內(nèi)容會(huì)強(qiáng)制寫入主存儲(chǔ)器(store->write),則這些計(jì)算結(jié)果就會(huì)對(duì)其它線程可見(visible)。

注意: 線程欲退出synchronized時(shí),不會(huì)執(zhí)行工作存儲(chǔ)器(working memory)的釋放 操作。

五、volatile的本質(zhì)

volatile具有以下兩種功能:

進(jìn)行內(nèi)存同步

volatile只能做內(nèi)存同步,不能取代synchronized關(guān)鍵字做線程同步。
當(dāng)線程欲引用volatile字段的值時(shí),通常都會(huì)發(fā)生從主存儲(chǔ)器到工作存儲(chǔ)器的拷貝操作;相反的,將值指定給寫著volatile的字段后,工作存儲(chǔ)器的內(nèi)容通常會(huì)立即映像到主存儲(chǔ)器

以原子(atomic)方式進(jìn)行l(wèi)ong、double的指定

六、Double Checked Locking Pattern的危險(xiǎn)性 6.1 可能存在缺陷的單例模式

設(shè)計(jì)模式中有一種單例模式(Singleton Pattern),通常采用鎖來保證線程的安全性。

Main類:

//兩個(gè)Main線程同時(shí)調(diào)用單例方法getInstance
public class Main extends Thread {
    public static void main(String[] args) {
        new Main().start();
        new Main().start();
    }
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":" + MySystem.getInstance().getDate());
    }
}

單例類:

//采用延遲加載+雙重鎖的形式保證線程安全以及性能
public class MySystem {
    private static MySystem instance = null;
    private Date date = new Date();
?
    private MySystem() {
    }
    public Date getDate() {
        return date;
    }
    public static MySystem getInstance() {
        if (instance == null) {
            synchronized (MySystem.class) {
                if (instance == null) {
                    instance = new MySystem();
                }
            }
        }
        return instance;
    }
}

分析:
上述Main類的MySystem.getInstance().getDate()調(diào)用可能返回null或其它值。
假設(shè)有兩個(gè)線程A和B,按照以下順序執(zhí)行:

當(dāng)線程A執(zhí)行完A-4且未退出synchronized時(shí),線程B開始執(zhí)行,此時(shí)B獲得了A創(chuàng)建好的instance實(shí)例。
但是注意,此時(shí)instance實(shí)例可能并未完全初始化完成。
這是因?yàn)榫€程A制作MySystem實(shí)例時(shí),會(huì)給date字段指定值new Date(),此時(shí)可能只完成了assign操作(線程A對(duì)工作存取器上的工作拷貝進(jìn)行指定),在線程A退出synchronized時(shí),線程A的工作存儲(chǔ)器上的值不保證一定會(huì)映像到主存儲(chǔ)器上(store->write)。

所以,當(dāng)線程B在線程A退出前就調(diào)用MySystem.getInstance().getDate()方法的話,由于主存儲(chǔ)器上的date字段并未被賦值過,所以B得到的date字段就是未初始化過的。

注意:上面描述的這種情況是否真的會(huì)發(fā)生,取決于JVM,由Java語(yǔ)言規(guī)范決定。

解決方法:
采用懶加載模式,在MySystem類中直接為instance 字段賦值:
private static MySystem instance = new MySystem();

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71490.html

相關(guān)文章

  • 深入理解Java內(nèi)存模型(一)——基礎(chǔ)

    摘要:線程之間的通信由內(nèi)存模型本文簡(jiǎn)稱為控制,決定一個(gè)線程對(duì)共享變量的寫入何時(shí)對(duì)另一個(gè)線程可見。為了保證內(nèi)存可見性,編譯器在生成指令序列的適當(dāng)位置會(huì)插入內(nèi)存屏障指令來禁止特定類型的處理器重排序。 并發(fā)編程模型的分類 在并發(fā)編程中,我們需要處理兩個(gè)關(guān)鍵問題:線程之間如何通信及線程之間如何同步(這里的線程是指并發(fā)執(zhí)行的活動(dòng)實(shí)體)。通信是指線程之間以何種機(jī)制來交換信息。在命令式編程中,線程之間的...

    jsdt 評(píng)論0 收藏0
  • 深入理解Java內(nèi)存模型)——重排序

    摘要:前情提要深入理解內(nèi)存模型一基礎(chǔ)編譯器運(yùn)行時(shí)會(huì)對(duì)指令進(jìn)行重排序。以處理器的猜測(cè)執(zhí)行為例,執(zhí)行線程的處理器可以提前讀取并計(jì)算,然后把計(jì)算結(jié)果臨時(shí)保存到一個(gè)名為重排序緩沖的硬件緩存中。請(qǐng)看下篇深入理解內(nèi)存模型三順序一致性 前情提要 深入理解Java內(nèi)存模型(一)——基礎(chǔ) Java編譯器、運(yùn)行時(shí)會(huì)對(duì)指令進(jìn)行重排序。這種重排序在單線程和多線程情況下分別有什么影響呢? 數(shù)據(jù)依賴性 如果兩個(gè)操...

    tunny 評(píng)論0 收藏0
  • Java面試 32個(gè)核心必考點(diǎn)完全解析

    摘要:如問到是否使用某框架,實(shí)際是是問該框架的使用場(chǎng)景,有什么特點(diǎn),和同類可框架對(duì)比一系列的問題。這兩個(gè)方向的區(qū)分點(diǎn)在于工作方向的側(cè)重點(diǎn)不同。 [TOC] 這是一份來自嗶哩嗶哩的Java面試Java面試 32個(gè)核心必考點(diǎn)完全解析(完) 課程預(yù)習(xí) 1.1 課程內(nèi)容分為三個(gè)模塊 基礎(chǔ)模塊: 技術(shù)崗位與面試 計(jì)算機(jī)基礎(chǔ) JVM原理 多線程 設(shè)計(jì)模式 數(shù)據(jù)結(jié)構(gòu)與算法 應(yīng)用模塊: 常用工具集 ...

    JiaXinYi 評(píng)論0 收藏0
  • Week 1 - Java 線程 - Java 內(nèi)存模型

    摘要:目的是解決由于多線程通過共享內(nèi)存進(jìn)行通信時(shí),存在的原子性可見性緩存一致性以及有序性問題。最多只有一個(gè)線程能持有鎖。線程加入規(guī)則對(duì)象的結(jié)束先行發(fā)生于方法返回。 前言 學(xué)習(xí)情況記錄 時(shí)間:week 1 SMART子目標(biāo) :Java 多線程 學(xué)習(xí)Java多線程,要了解多線程可能出現(xiàn)的并發(fā)現(xiàn)象,了解Java內(nèi)存模型的知識(shí)是必不可少的。 對(duì)學(xué)習(xí)到的重要知識(shí)點(diǎn)進(jìn)行的記錄。 注:這里提到的是Ja...

    zhaofeihao 評(píng)論0 收藏0
  • 程序語(yǔ)言

    摘要:一面應(yīng)該還問了其他內(nèi)容,但是兩次面試多線程面試問題和答案采訪中,我們通常會(huì)遇到兩個(gè)主題采集問題和多線程面試問題。多線程是關(guān)于并發(fā)和線程的。我們正在共享重要的多線程面試問題和答案。。 2016 年末,騰訊,百度,華為,搜狗和滴滴面試題匯總 2016 年未,騰訊,百度,華為,搜狗和滴滴面試題匯總 【碼農(nóng)每日一題】Java 內(nèi)部類(Part 2)相關(guān)面試題 關(guān)注一下嘛,又不讓你背鍋!問:Ja...

    mtunique 評(píng)論0 收藏0

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

0條評(píng)論

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