真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

為什么要學(xué)習(xí)Java并發(fā)

本篇內(nèi)容主要講解“為什么要學(xué)習(xí)Java并發(fā)”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“為什么要學(xué)習(xí)Java并發(fā)”吧!

因?yàn)榕驼嬲\(chéng),有更多的客戶和我們聚集在一起,為了共同目標(biāo),成都創(chuàng)新互聯(lián)在工作上密切配合,從創(chuàng)業(yè)型企業(yè)到如今不斷成長(zhǎng),要感謝客戶對(duì)我們的高要求,讓我們敢于面對(duì)挑戰(zhàn),才有今天的進(jìn)步與發(fā)展。從網(wǎng)站到重慶小程序開發(fā),軟件開發(fā),成都App定制開發(fā),十余年企業(yè)網(wǎng)站建設(shè)服務(wù)經(jīng)驗(yàn),為企業(yè)提供網(wǎng)站設(shè)計(jì),網(wǎng)站托管運(yùn)營(yíng)一條龍服務(wù).為企業(yè)提供營(yíng)銷型網(wǎng)站,專業(yè)公司,原創(chuàng)設(shè)計(jì),十余年品質(zhì),值得您的信賴.

01

初識(shí)并發(fā)

什么是并發(fā),什么是并行? 

用個(gè)JVM的例子來講解,在垃圾回收器做并發(fā)標(biāo)記的時(shí)候,這個(gè)時(shí)候JVM不僅可以做垃圾標(biāo)記,還可以處理程序的一些需求,這個(gè)叫并發(fā)。在做垃圾回收時(shí),JVM多個(gè)線程同時(shí)做回收,這叫并行。

02

為什么要學(xué)習(xí)并發(fā)編程

直觀原因
1)JD的強(qiáng)制性要求
隨著互聯(lián)網(wǎng)行業(yè)的飛速發(fā)展,并發(fā)編程已經(jīng)成為非常熱門的領(lǐng)域,也是各大企業(yè)服務(wù)端崗位招聘的必備技能。

2)從小牛通往大牛的必經(jīng)之路
架構(gòu)師是軟件開發(fā)團(tuán)隊(duì)中非常重要的角色,成為一名架構(gòu)師是許多搞技術(shù)人奮斗的目標(biāo),衡量一個(gè)架構(gòu)師的能力指標(biāo)就是設(shè)計(jì)出一套解決高并發(fā)的系統(tǒng),由此可見高并發(fā)技術(shù)的重要性,而并發(fā)編程是底層的基礎(chǔ)。無論游戲還是互聯(lián)網(wǎng)行業(yè),無論軟件開發(fā)還是大型網(wǎng)站,都對(duì)高并發(fā)技術(shù)人才存在巨大需求,因此,為了工作為了提升自己,學(xué)習(xí)高并發(fā)技術(shù)刻不容緩。

3)面試過程中極容易踩坑
面試的時(shí)候?yàn)榱丝疾鞂?duì)并發(fā)編程的掌握情況,經(jīng)常會(huì)考察并發(fā)安全相關(guān)的知識(shí)和線程交互的知識(shí)。例如在并發(fā)情況下如何實(shí)現(xiàn)一個(gè)線程安全的單例模式,如何完成兩個(gè)線程中的功能交互執(zhí)行。

以下是使用雙檢索實(shí)現(xiàn)一個(gè)線程安全的單例懶漢模式,當(dāng)然也可以使用枚舉或者單例餓漢模式。

    private static volatile  Singleton singleton;    private Singleton(){};    public Singleton getSingleton(){        if(null == singleton){            synchronized(Singleton.class){                if(null == singleton){                    singleton = new Singleton();                }            }        }        return singleton;    }

在這里第一層空判斷是為了減少鎖控制的粒度,使用volatile修飾是因?yàn)樵趈vm中new Singleton()會(huì)出現(xiàn)指令重排,volatile避免happens before,避免空指針的問題。從一個(gè)線程安全的單例模式可以引申出很多,volatile和synchronized的實(shí)現(xiàn)原理,JMM模型,MESI協(xié)議,指令重排,關(guān)于JMM模型后序會(huì)給出更詳細(xì)的圖解。

除了線程安全問題,還會(huì)考察線程間的交互。 例如使用兩個(gè)線程交替打印出A1B2C3…Z26

為什么要學(xué)習(xí)Java并發(fā)

考察的重點(diǎn)并不是要簡(jiǎn)單的實(shí)現(xiàn)這個(gè)功能,通過此面試題,可以考察知識(shí)的整體掌握情況,多種方案實(shí)現(xiàn),可以使用Atomicinteger、ReentrantLock、CountDownLat ch。下圖是使用LockSupport控制兩個(gè)線程交替打印的示例,LockSupport內(nèi)部實(shí)現(xiàn)的原理是使用UNSAFE控制一個(gè)信號(hào)量在0和1之間變動(dòng),從而可以控制兩個(gè)線程的交替打印。

4)并發(fā)在我們工作使用的框架中處處可見,tom cat,netty,jvm,Disruptor

熟悉JAVA并發(fā)編程基礎(chǔ)是掌握這些框架底層知識(shí)的基石,這里簡(jiǎn)單介紹下高并發(fā)框架Disruptor的底層實(shí)現(xiàn)原理,做一個(gè)勾勒的作用:
Martin Fowler在一篇LMAX文章中介紹,這一個(gè)高性能異步處理框架,其單線程一秒的吞吐量可達(dá)六百萬

Disruptor核心概念

為什么要學(xué)習(xí)Java并發(fā)

Disruptor特征

  • 基于事件驅(qū)動(dòng)

  • 基于"觀察者"模式、"生產(chǎn)者-消費(fèi)者"模型

  • 可以在無鎖的情況下實(shí)現(xiàn)網(wǎng)絡(luò)的隊(duì)列操作

RingBuffer執(zhí)行流程

為什么要學(xué)習(xí)Java并發(fā)

Disruptor底層組件,RingBuffer密切相關(guān)的對(duì)象:Sequ enceBarrier和Sequencer;

SequenceBarrier是消費(fèi)者和RingBuffer之間的橋梁。在Disruptor中,消費(fèi)者直接訪問的是SequenceBarrier,由SequenceBarrier減少RingBuffer的隊(duì)列沖突。

SequenceBarrier 通過waitFor方法當(dāng)消費(fèi)者速度大于生產(chǎn)者的生產(chǎn)速度時(shí),消費(fèi)者可通過waitFor方法給予生產(chǎn)者一定的緩沖時(shí)間,協(xié)調(diào)生產(chǎn)者和消費(fèi)者的速度問題,waitFor執(zhí)行時(shí)機(jī):

為什么要學(xué)習(xí)Java并發(fā)

Sequencer是生產(chǎn)者和緩沖區(qū)RingBuffer之間的橋梁,生產(chǎn)者通過Sequencer向RingBuffer申請(qǐng)數(shù)據(jù)存放空間,通過WaitStrategy使用publish方法通知消費(fèi)者,WaitStrategy是消費(fèi)者沒有數(shù)據(jù)可以消費(fèi)時(shí)的等待策略。每個(gè)生產(chǎn)者或者消費(fèi)者線程,會(huì)先申請(qǐng)可以操作的元素在數(shù)組中的位置,申請(qǐng)到之后,直接在該位置寫入或者讀取數(shù)據(jù),整個(gè)過程通過原子變量CAS,保證操作的線程安全,這就是Disruptor的無鎖設(shè)計(jì)。

以下是五大常用等待策略:
BlockingWaitStrategy:Disruptor的默認(rèn)策略是BlockingWaitStrategy。在BlockingWaitStrategy內(nèi)部是使用鎖和condition來控制線程的喚醒。BlockingWaitStrategy是最低效的策略,但其對(duì)CPU的消耗最小并且在各種不同部署環(huán)境中能提供更加一致的性能表現(xiàn)。

SleepingWaitStrategy:SleepingWaitStrategy 的性能表現(xiàn)跟 BlockingWaitStrategy 差不多,對(duì) CPU 的消耗也類似,但其對(duì)生產(chǎn)者線程的影響最小,通過使用LockSupport.parkNanos(1)來實(shí)現(xiàn)循環(huán)等待。

YieldingWaitStrategy:YieldingWaitStrategy是可以使用在低延遲系統(tǒng)的策略之一。YieldingWaitStrategy將自旋以等待序列增加到適當(dāng)?shù)闹怠T谘h(huán)體內(nèi),將調(diào)用Thread.yield()以允許其他排隊(duì)的線程運(yùn)行。在要求極高性能且事件處理線數(shù)小于 CPU 邏輯核心數(shù)的場(chǎng)景中,推薦使用此策略;例如,CPU開啟超線程的特性。

BusySpinWaitStrategy:性能最好,適合用于低延遲的系統(tǒng)。在要求極高性能且事件處理線程數(shù)小于CPU邏輯核心數(shù)的場(chǎng)景中,推薦使用此策略;例如,CPU開啟超線程的特性。

目前,包括Apache Storm、Camel、Log4j2在內(nèi)的很多知名項(xiàng)目都應(yīng)用了Disruptor以獲取高性能。

5)JUC是并發(fā)大神Doug Lea靈魂力作,堪稱典范(第一個(gè)主流嘗試,它將線程,鎖和事件之外的抽象層次提升到更平易近人的方式:并發(fā)集合, fork/join 等等)

通過并發(fā)編程設(shè)計(jì)思維的學(xué)習(xí),發(fā)揮使用多線程的優(yōu)勢(shì)

  • 發(fā)揮多處理器的強(qiáng)大能力

  • 建模的簡(jiǎn)單性

  • 異步事件的簡(jiǎn)化處理

  • 響應(yīng)更靈敏的用戶界面

那么學(xué)不好并發(fā)編程基礎(chǔ)會(huì)帶來什么問題呢

1)多線程在日常開發(fā)中運(yùn)用中處處都是,jvm、tomcat、netty,學(xué)好java并發(fā)編程是更深層次理解和掌握此類工具和框架的前提由于計(jì)算機(jī)的cpu運(yùn)算速度和內(nèi)存io速度有幾個(gè)數(shù)量級(jí)的差距,因此現(xiàn)代計(jì)算機(jī)都不得不加入一層盡可能接近處理器運(yùn)算速度的高速緩存來做緩沖:將內(nèi)存中運(yùn)算需要使用的數(shù)據(jù)先復(fù)制到緩存中,當(dāng)運(yùn)算結(jié)束后再同步回內(nèi)存。如下圖:

為什么要學(xué)習(xí)Java并發(fā)

因?yàn)閖vm要實(shí)現(xiàn)跨硬件平臺(tái),因此jvm定義了自己的內(nèi)存模型,但是因?yàn)閖vm的內(nèi)存模型最終還是要映射到硬件上,因此jvm內(nèi)存模型幾乎與硬件的模型一樣:

為什么要學(xué)習(xí)Java并發(fā)

操作系統(tǒng)底層數(shù)據(jù)結(jié)構(gòu),每個(gè)CPU對(duì)應(yīng)的高速緩存中的數(shù)據(jù)結(jié)構(gòu)是一個(gè)個(gè)bucket存儲(chǔ)的鏈表,其中tag代表的是主存中的地址,cache line是偏移量,flag對(duì)應(yīng)的MESI緩存一致性協(xié)議中的各個(gè)狀態(tài)。

MESI緩存一致性狀態(tài)分別為:

M:Modify,代表修改

E:Exclusive,代表獨(dú)占

S:Share,代表共享

I:Invalidate,代表失效

以下是一次cpu0數(shù)據(jù)寫入的流程:

  • 在CPU0執(zhí)行一次load,read和write時(shí),在做write之前flag的狀態(tài)會(huì)是S,然后發(fā)出invalidate消息到總線;

  • 其他cpu會(huì)監(jiān)聽總線消息,將各cpu對(duì)應(yīng)的cache entry中的flag狀態(tài)由S修改為I,并且發(fā)送invalidate ack給總線

  • cpu0收到所有cpu返回的invalidate ack后,cpu0將flag變?yōu)镋,執(zhí)行數(shù)據(jù)寫入,狀態(tài)修改為M,類似于一個(gè)加鎖過程

考慮到性能問題,這樣寫入修改數(shù)據(jù)的效率太過漫長(zhǎng),因此引入了寫緩沖器和無效隊(duì)列,所有的修改操作會(huì)先寫入寫緩沖器,其他cpu接收到消息后會(huì)先寫入無效隊(duì)列,并返回ack消息,之后再?gòu)臒o效隊(duì)列消費(fèi)消息,采用異步的形式。當(dāng)然,這樣就會(huì)產(chǎn)生有序性問題,例如某些entry中的flag還是S,但實(shí)際上應(yīng)該標(biāo)識(shí)為I,這樣訪問到的數(shù)據(jù)就會(huì)有問題。運(yùn)用volitale是為了解決指令重排帶來的無序性問題,volitale是jvm層面的關(guān)鍵字,MESI是cpu層面的,兩者是差了幾個(gè)層次的。

為什么要學(xué)習(xí)Java并發(fā)

2)性能不達(dá)標(biāo),找不到解決思路。

3)工作中可能會(huì)寫出線程不安全的方法
以下是一個(gè)多線程打印時(shí)間的逐步優(yōu)化案例

new Thread(new Runnable() {    @Override    public void run() {        System.out.println(new ThreadLocalDemo01().date(10));    }}).start();new Thread(new Runnable() {    @Override    public void run() {        System.out.println(new ThreadLocalDemo01().date(1007));    }}).start();

優(yōu)化1,多個(gè)線程運(yùn)用線程池復(fù)用

for(int i = 0; i < 1000; i++){    int finalI = i;    executorService.submit(new Runnable() {        @Override        public void run() {            System.out.println(new ThreadLocalDemo01().date2(finalI));        }    });}executorService.shutdown();public String date2(int seconds){        Date date = new Date(1000 * seconds);        String s = null;//        synchronized (ThreadLocalDemo01.class){//            s = simpleDateFormat.format(date);//        }        s = simpleDateFormat.format(date);        return s;}

優(yōu)化2,線程池結(jié)合ThreadLocal

public String date2(int seconds){    Date date = new Date(1000 * seconds);    SimpleDateFormat simpleDateFormat = ThreadSafeFormatter.dateFormatThreadLocal.get();    return simpleDateFormat.format(date);}

在多線程服用一個(gè)SimpleDateFormat時(shí)會(huì)出現(xiàn)線程安全問題,執(zhí)行結(jié)果會(huì)打印出相同的時(shí)間,在優(yōu)化2中使用線程池結(jié)合ThreadLocal實(shí)現(xiàn)資源隔離,線程安全。

4)許多問題無法正確定位
踩坑:crm仿真定時(shí)任務(wù)阻塞,無法繼續(xù)執(zhí)行
問題:crm仿真運(yùn)用schedule配置的定時(shí)任務(wù)在某個(gè)時(shí)間節(jié)點(diǎn)后的所有定時(shí)任務(wù)均未執(zhí)行
原因:定時(shí)任務(wù)配置導(dǎo)致的問題,@Schedule配置的定時(shí)任務(wù)如果未配置線程池,在啟動(dòng)類使用@EnableScheduling啟用定時(shí)任務(wù)時(shí)會(huì)默認(rèn)使用單線程,后端配置了多定時(shí)任務(wù),會(huì)出現(xiàn)問題.配置了兩定時(shí)任務(wù)A和B,在A先占用資源后如果一直未釋放,B會(huì)一直處于等待狀態(tài),直到A任務(wù)釋放資源后,B開始執(zhí)行,若要避免多任務(wù)執(zhí)行帶來的問題,需要使用以下方法配置:

@Bean public ThreadPoolTaskScheduler taskScheduler(){   ThreadPoolTaskScheduler scheduler = new       ThreadPoolTaskScheduler();   scheduler.setPoolSize(10);   return scheduler; }

crm服務(wù)由于定時(shí)任務(wù)配置的不多,并且在資源足夠的情況下,任務(wù)執(zhí)行速度相對(duì)較快,并未設(shè)置定時(shí)任務(wù)的線程池

定時(shí)任務(wù)里程序方法如何造成線程一直未釋放,導(dǎo)致阻塞。

在問題定位時(shí),產(chǎn)生的問題來自CountDownLatch無法歸零,導(dǎo)致整個(gè)主線程hang在那里,無法釋放。

在api中當(dāng)調(diào)用await時(shí)候,調(diào)用線程處于等待掛起狀態(tài),直至count變成0再繼續(xù),大致原理如下:

為什么要學(xué)習(xí)Java并發(fā)

因此將目光焦點(diǎn)轉(zhuǎn)移至await方法,使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直等待,除非線程被中斷或超出了指定的等待時(shí)間。如果當(dāng)前計(jì)數(shù)為零,則此方法立刻返回true 值。如果當(dāng)前計(jì)數(shù)大于零,則出于線程調(diào)度目的,將禁用當(dāng)前線程,且在發(fā)生以下三種情況之一前,該線程將一直處于休眠狀態(tài):由于調(diào)用 countDown() 方法,計(jì)數(shù)到達(dá)零;或者其他某個(gè)線程中斷當(dāng)前線程;或者已超出指定的等待時(shí)間。

Executors.newFixedThreadPool這是個(gè)有固定活動(dòng)線程數(shù)。當(dāng)提交到池中的任務(wù)數(shù)大于固定活動(dòng)線程數(shù)時(shí),任務(wù)就會(huì)放到阻塞隊(duì)列中等待。CRM該定時(shí)任務(wù)里為了加快任務(wù)處理,運(yùn)用多線程處理,設(shè)置的CountDownLatch的count大于ThreadPoolExecutor的固定活動(dòng)線程數(shù)導(dǎo)致任務(wù)一直處于等待狀態(tài),計(jì)數(shù)無法歸零,導(dǎo)致主線程一直無法釋放,從而導(dǎo)致crm一臺(tái)仿真服務(wù)的定時(shí)任務(wù)處于癱瘓狀態(tài)。

03

如何學(xué)習(xí)java并發(fā)編程

為了學(xué)習(xí)好并發(fā)編程基礎(chǔ),我們需要有一個(gè)上帝視角,一個(gè)宏觀的概念,然后由點(diǎn)及深,掌握必備的知識(shí)點(diǎn)。我們可以從以下兩張思維導(dǎo)圖列舉出來的逐步進(jìn)行學(xué)習(xí)。

為什么要學(xué)習(xí)Java并發(fā)

必備知識(shí)點(diǎn)

為什么要學(xué)習(xí)Java并發(fā)

04

線程

列舉了如此多的案例都是圍繞線程展開的,所以我們需要更深地掌握線程,它的概念,它的原則,它是如何實(shí)現(xiàn)交互通信的。

以下的一張圖可以更通俗地解釋進(jìn)程、線程的區(qū)別

為什么要學(xué)習(xí)Java并發(fā)

進(jìn)程: 一個(gè)進(jìn)程好比是一個(gè)程序,它是 資源分配的最小單位 。同一時(shí)刻執(zhí)行的進(jìn)程數(shù)不會(huì)超過核心數(shù)。不過如果問單核CPU能否運(yùn)行多進(jìn)程?答案又是肯定的。單核CPU也可以運(yùn)行多進(jìn)程,只不過不是同時(shí)的,而是極快地在進(jìn)程間來回切換實(shí)現(xiàn)的多進(jìn)程。電腦中有許多進(jìn)程需要處于「同時(shí)」開啟的狀態(tài),而利用CPU在進(jìn)程間的快速切換,可以實(shí)現(xiàn)「同時(shí)」運(yùn)行多個(gè)程序。而進(jìn)程切換則意味著需要保留進(jìn)程切換前的狀態(tài),以備切換回去的時(shí)候能夠繼續(xù)接著工作。所以進(jìn)程擁有自己的地址空間,全局變量,文件描述符,各種硬件等等資源。操作系統(tǒng)通過調(diào)度CPU去執(zhí)行進(jìn)程的記錄、回復(fù)、切換等等。

線程:線程是獨(dú)立運(yùn)行和獨(dú)立調(diào)度的基本單位(CPU上真正運(yùn)行的是線程),線程相當(dāng)于一個(gè)進(jìn)程中不同的執(zhí)行路徑。

單線程:單線程就是一個(gè)叫做“進(jìn)程”的房子里面,只住了你一個(gè)人,你可以在這個(gè)房子里面任何時(shí)間去做任何的事情。你是看電視、還是玩電腦,全都有你自己說的算。想干什么干什么,想什么時(shí)間做什么就什么時(shí)間做什么。

多線程:但是如果你處在一個(gè)“多人”的房子里面,每個(gè)房子里面都有叫做“線程”的住戶:線程1、線程2、線程3、線程4,情況就不得不發(fā)生變化了。

在多線程編程中有”鎖”的概念,在你的房子里面也有鎖。如果你的老婆在上廁所并鎖上門,她就是在獨(dú)享這個(gè)“房子(進(jìn)程)”里面的公共資源“衛(wèi)生間”,如果你的家里只有這一個(gè)衛(wèi)生間,你作為另外一個(gè)線程就只能先等待。

為什么要學(xué)習(xí)Java并發(fā)

線程最為重要也是最為麻煩的就是線程間的交互通信過程,下圖是線程狀態(tài)的變化過程:

為什么要學(xué)習(xí)Java并發(fā)

為了闡述線程間的通信,簡(jiǎn)單模擬一個(gè)生產(chǎn)者消費(fèi)者模型:

生產(chǎn)者

CarStock carStock;public CarProducter(CarStock carStock){    this.carStock = carStock;}@Overridepublic void run() {    while (true){        carStock.produceCar();    }}public synchronized void produceCar(){  try {    if(cars < 20){      System.out.println("生產(chǎn)者..." + cars);      Thread.sleep(100);      cars++;      notifyAll();    }else {      wait();    }  } catch (InterruptedException e) {    e.printStackTrace();  }}

消費(fèi)者

CarStock carStock;public CarConsumer(CarStock carStock){    this.carStock = carStock;}@Overridepublic void run() {    while (true){        carStock.consumeCar();    }}public synchronized void consumeCar(){    try {        if(cars > 0){            System.out.println("銷售車..." + cars);            Thread.sleep(100);            cars--;            notifyAll();        }else {            wait();        }    } catch (InterruptedException e) {        e.printStackTrace();    }}

消費(fèi)過程

為什么要學(xué)習(xí)Java并發(fā)

通信過程

為什么要學(xué)習(xí)Java并發(fā)

對(duì)于此簡(jiǎn)單的生產(chǎn)者消費(fèi)者模式可以運(yùn)用隊(duì)列、線程池等技術(shù)對(duì)程序進(jìn)行改進(jìn),運(yùn)用BolckingQueue隊(duì)列共享數(shù)據(jù),改進(jìn)后的消費(fèi)過程

為什么要學(xué)習(xí)Java并發(fā)

05

并發(fā)編程三大特性

并發(fā)編程實(shí)現(xiàn)機(jī)制大多都是圍繞以下三點(diǎn):原子性、可見性、有序性

1)原子性問題

for(int i = 0; i < 20; i++){    Thread thread = new Thread(() -> {        for (int j = 0; j < 10000; j++) {            res++;            normal++;            atomicInteger.incrementAndGet();        }    });    thread.start();}

運(yùn)行結(jié)果:

volatile: 170797
atomicInteger:200000
normal:182406

這就是原子性問題,原子性是指在一個(gè)操作中就是cpu不可以在中途暫停然后再調(diào)度,既不被中斷操作,要不執(zhí)行完成,要不就不執(zhí)行。
如果一個(gè)操作是原子性的,那么多線程并發(fā)的情況下,就不會(huì)出現(xiàn)變量被修改的情況。

2)可見性問題

class MyThread extends Thread{    public int index = 0;    @Override    public void run() {        System.out.println("MyThread Start");        while (true) {            if (index == -1) {                break;            }        }        System.out.println("MyThread End");    }}

main線程將index修改為-1,myThread線程并不可見,這就是可見性問題導(dǎo)致的線程安全,可見性就是指當(dāng)一個(gè)線程修改了線程共享變量的值,其它線程能夠立即得知這個(gè)修改。Java內(nèi)存模型是通過在變量修改后將新值同步回主內(nèi)存,在變量讀取前從主內(nèi)存刷新變量值這種依賴主內(nèi)存作為傳遞媒介的方法來實(shí)現(xiàn)可見性的,無論是普通變量還是volatile變量都是如此,普通變量與volatile變量的區(qū)別是volatile的特殊規(guī)則保證了新值能立即同步到主內(nèi)存,以及每使用前立即從內(nèi)存刷新。因?yàn)槲覀兛梢哉fvolatile保證了線程操作時(shí)變量的可見性,而普通變量則不能保證這一點(diǎn)。

3)有序性問題

雙檢索單例懶漢模式

為什么要學(xué)習(xí)Java并發(fā)

有序性: Java內(nèi)存模型中的程序天然有序性可以總結(jié)為一句話:如果在本線程內(nèi)觀察,所有操作都是有序的;如果在一個(gè)線程中觀察另一個(gè)線程,所有操作都是無序的。前半句是指“線程內(nèi)表現(xiàn)為串行語(yǔ)義”,后半句是指“指令重排序”現(xiàn)象和“工作內(nèi)存中主內(nèi)存同步延遲”現(xiàn)象。

到此,相信大家對(duì)“為什么要學(xué)習(xí)Java并發(fā)”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


文章題目:為什么要學(xué)習(xí)Java并發(fā)
URL鏈接:http://weahome.cn/article/gjcppe.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部