JAVA虛擬機(jī)高效并發(fā)的案例分析-創(chuàng)新互聯(lián)

這篇文章主要介紹了JAVA虛擬機(jī)高效并發(fā)的案例分析,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

介休網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,介休網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為介休近1000家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的介休做網(wǎng)站的公司定做!

                                                           JAVA虛擬機(jī)高效并發(fā)的案例分析

內(nèi)存模型

內(nèi)存模型是在特定的操作協(xié)議下,對(duì)特定的內(nèi)存或高速緩存進(jìn)行讀寫(xiě)訪問(wèn)的過(guò)程抽象。其主要目標(biāo)是定義程序中各個(gè)變量的訪問(wèn)規(guī)則。

主內(nèi)存和工作內(nèi)存

JAVA虛擬機(jī)高效并發(fā)的案例分析

所有的變量都存儲(chǔ)在主內(nèi)存中,每條線程還有自己的工作內(nèi)存,其工作內(nèi)存中是被線程使用到的變量的主內(nèi)存副本拷貝,線程對(duì)變量的讀取、賦值等操作都必須在工作內(nèi)存中進(jìn)行,而不能直接讀取主內(nèi)存中的變量。

內(nèi)存間交互操作

從主內(nèi)存拷貝到工作內(nèi)存:順序地執(zhí)行read和load操作。
工作內(nèi)存同步到主內(nèi)存:store和write操作。

volatile的特性

Volatile的作用和synchronized相同,但是和synchronized相比,更輕量。其特性主要有如下兩點(diǎn):

保證此變量對(duì)所有線程的可見(jiàn)性

啥意思呢?指當(dāng)一個(gè)線程修改了這個(gè)變量的值,新值對(duì)于其他線程來(lái)說(shuō)是立即可知的。而普通變量做不到這一點(diǎn),普通變量的值在線程間傳遞均需要通過(guò)主內(nèi)存來(lái)完成,比如線程A修改了一個(gè)普通變量的值,然后向主內(nèi)存進(jìn)行回寫(xiě),另外一條線程B在線程A回寫(xiě)完成了之后再?gòu)闹鲀?nèi)存進(jìn)行讀取操作,新變量值才會(huì)對(duì)線程B可見(jiàn)。

禁止指令重排序優(yōu)化

因?yàn)橹噶钪嘏判驎?huì)干擾程序的并發(fā)執(zhí)行。

多線程

為什么需要多線程?

計(jì)算機(jī)的運(yùn)算速度與它的存儲(chǔ)和通信子系統(tǒng)速度的差距太大,大量的時(shí)間都花費(fèi)在磁盤(pán)I/O、網(wǎng)絡(luò)通信、數(shù)據(jù)庫(kù)訪問(wèn)上了。使用多線程能更好地利用cpu。

有哪些并發(fā)應(yīng)用場(chǎng)景?

充分利用計(jì)算機(jī)處理器

一個(gè)服務(wù)端同時(shí)對(duì)多個(gè)客戶(hù)端提供服務(wù)

如何使處理器內(nèi)部的運(yùn)算單元被充分利用?

加入一層高速緩存

將運(yùn)算需要使用到的數(shù)據(jù)復(fù)制到緩存中,讓運(yùn)算能快速進(jìn)行。當(dāng)運(yùn)算結(jié)束后再?gòu)木彺嫱交貎?nèi)存中,這樣處理器就無(wú)須等待緩慢的內(nèi)存讀寫(xiě)了。不過(guò)這個(gè)要考慮一個(gè)問(wèn)題:怎么保證緩存的一致性。

JAVA虛擬機(jī)高效并發(fā)的案例分析

對(duì)輸入代碼進(jìn)行亂序執(zhí)行優(yōu)化

線程的實(shí)現(xiàn)方式

使用內(nèi)核線程實(shí)現(xiàn)

內(nèi)核線程就是直接由操作系統(tǒng)內(nèi)核支持的線程。

使用用戶(hù)線程實(shí)現(xiàn)

用戶(hù)線程的建立、同步、銷(xiāo)毀和調(diào)度完全在用戶(hù)態(tài)中完成,不需要內(nèi)核的幫助,內(nèi)核也感知不到線程存在的實(shí)現(xiàn)。這種實(shí)現(xiàn)方式使用較少。

使用用戶(hù)線程加輕量級(jí)進(jìn)行混合實(shí)現(xiàn)

合并到一起

線程調(diào)度

線程調(diào)度是指系統(tǒng)為線程分配處理器使用權(quán)的過(guò)程。主要分為兩種:協(xié)同式和搶占式。

協(xié)同式

線程的執(zhí)行時(shí)間由線程本身來(lái)控制,線程把自己的工作執(zhí)行完了,會(huì)主動(dòng)通知系統(tǒng)切換到另外一個(gè)線程上。
其優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單,而且沒(méi)有線程同步的問(wèn)題。缺點(diǎn)是如果一個(gè)線程編寫(xiě)有問(wèn)題,一直不告訴系統(tǒng)進(jìn)行線程切換,那程序就會(huì)一直阻塞在那里,容易導(dǎo)致系統(tǒng)崩潰。

搶占式

線程將由系統(tǒng)來(lái)分配執(zhí)行時(shí)間,線程切換不由本身來(lái)決定。java使用的線程調(diào)度方式就是這種。

線程安全

當(dāng)多個(gè)線程訪問(wèn)一個(gè)對(duì)象時(shí),如果不考慮這個(gè)線程在運(yùn)行時(shí)環(huán)境下的調(diào)度和交替執(zhí)行,也不需要進(jìn)行額外的同步,或者在調(diào)用方進(jìn)行任何其它的協(xié)調(diào)操作,調(diào)用這個(gè)對(duì)象的行為都可以獲得正確的結(jié)果,那這個(gè)對(duì)象就是安全的。

共享數(shù)據(jù)的分類(lèi)

不可變

不可變的共享數(shù)據(jù)是用final修飾的數(shù)據(jù),其一定是線程安全的。如果共享數(shù)據(jù)是一個(gè)基本類(lèi)型變量,那么只要在定義的時(shí)候使用final關(guān)鍵字即可。

如果共享數(shù)據(jù)是一個(gè)對(duì)象,那就需要對(duì)象的行為不會(huì)對(duì)其狀態(tài)產(chǎn)生影響,可以將對(duì)象中帶有狀態(tài)的變量都聲明為final。比如String類(lèi)就是一個(gè)不可變類(lèi)

絕對(duì)線程安全

在Java API中標(biāo)注自己是線程安全的類(lèi),大多數(shù)都不是絕對(duì)的線程安全。比如Vector是一個(gè)線程安全的集合,它的所有的方法都被修飾成同步,但是在多線程的環(huán)境中,它依舊不是同步的。

相對(duì)線程安全

相對(duì)線程安全就是我們通常意義上所說(shuō)的線程安全,它只能保證對(duì)這個(gè)對(duì)象單獨(dú)操作是線程安全的。但是對(duì)于一些特定順序的連續(xù)調(diào)用,就可能需要在調(diào)用端使用額外的同步手段來(lái)保證調(diào)用的正確性。
大部分的線程安全類(lèi)都屬于這種類(lèi)型。

線程兼容

對(duì)象本身不是線性安全的,但可以通過(guò)在調(diào)用端正確地使用同步手段來(lái)保證對(duì)象在并發(fā)環(huán)境中可以安全的使用。大部分的不是線程安全的類(lèi),都屬于這種類(lèi)型。

線程對(duì)立

無(wú)論怎樣,都不能在多線程環(huán)境中并發(fā)使用,如System.setIn()、System.SetOut()。一個(gè)對(duì)輸入進(jìn)行修改,一個(gè)對(duì)輸出進(jìn)行修改,兩者是不能“交替”進(jìn)行的。

實(shí)現(xiàn)方法

方式一:互斥同步——悲觀并發(fā)策略

(1)synchronized

其原理是:這個(gè)關(guān)鍵字在經(jīng)過(guò)編譯后,會(huì)在同步塊的前后分別形成monitorenter和monitorexit這兩個(gè)字節(jié)碼指令。當(dāng)執(zhí)行monitorenter指令時(shí),程序會(huì)嘗試獲取對(duì)象的鎖,如果能獲取到,則把鎖的計(jì)數(shù)器+1,相應(yīng)的,在執(zhí)行monitorexit時(shí),會(huì)將鎖計(jì)數(shù)器-1。當(dāng)計(jì)數(shù)器為0時(shí),鎖就被釋放。

其特點(diǎn)是:對(duì)同一條線程來(lái)說(shuō)是可重入的;同步塊在已進(jìn)入的線程執(zhí)行完之前,會(huì)阻塞后面的其他線程進(jìn)入。

其選用場(chǎng)景是:在確實(shí)必要的情況下才使用此,因?yàn)槠涫侵亓考?jí)的。

(2)ReentrantLock

此重入鎖是java.util.concurrent(JUC)包下的類(lèi)。其高級(jí)特性有:等待可中斷、可實(shí)現(xiàn)公平鎖、鎖可以綁定多個(gè)條件。

方式二:非阻塞同步——樂(lè)觀并發(fā)策略

先進(jìn)行操作,如果沒(méi)有其它線程爭(zhēng)用共享數(shù)據(jù),那操作就是成功了;如果共享數(shù)據(jù)有爭(zhēng)用,產(chǎn)生了沖突,那就再采取其它的補(bǔ)償措施。

方式三:無(wú)同步方案

如果一個(gè)方法本來(lái)就不涉及共享數(shù)據(jù),那就沒(méi)有必要進(jìn)行同步措施。比如可重復(fù)代碼和線程本地存儲(chǔ)。

(1)可重入代碼

如果一個(gè)方法,它的返回結(jié)果是可預(yù)測(cè)的,只要輸入了相同的數(shù)據(jù),就都能返回相同的結(jié)果,那它就滿(mǎn)足可重入的要求。

(2)線程本地存儲(chǔ)

如果一段代碼中所需要的數(shù)據(jù)必須與其它代碼共享,而且這些共享數(shù)據(jù)的代碼在同一個(gè)線程中執(zhí)行,如此,我們可以把共享數(shù)據(jù)的可見(jiàn)范圍限制在一個(gè)線程中,這樣,就不用同步也能保證線程之間不出現(xiàn)數(shù)據(jù)爭(zhēng)用問(wèn)題。

鎖優(yōu)化

適應(yīng)性自旋

因?yàn)樽枞蛘邌拘岩粋€(gè)JAVA的線程需要操作系統(tǒng)切換CPU狀態(tài)來(lái)完成,這種狀態(tài)的轉(zhuǎn)換需要耗費(fèi)處理器時(shí)間。如果同步代碼塊中的內(nèi)容過(guò)于簡(jiǎn)單,很可能導(dǎo)致?tīng)顟B(tài)轉(zhuǎn)換消耗的時(shí)間比用戶(hù)代碼執(zhí)行的時(shí)間還要長(zhǎng)。

為了解決這個(gè)問(wèn)題,我們可以讓后面請(qǐng)求鎖的線程“稍等一下”,執(zhí)行一個(gè)忙循環(huán),進(jìn)行自旋。此時(shí)沒(méi)有放棄處理器的執(zhí)行時(shí)間。如果自旋超過(guò)了限定的次數(shù),仍然沒(méi)有成功獲得鎖,那就會(huì)使用傳統(tǒng)的方式去掛起線程了。

那什么叫做適應(yīng)性自旋呢?

就是在同一個(gè)鎖對(duì)象上,如果自旋等待剛剛成功獲得過(guò)鎖,那虛擬機(jī)就會(huì)認(rèn)為這次自旋獲得鎖的概率挺大,就會(huì)允許其自旋等待持續(xù)相對(duì)更長(zhǎng)的時(shí)間。相反,如果自旋很少成功獲得過(guò)鎖,則可能省略掉自旋過(guò)程。

鎖消除

指虛擬機(jī)即時(shí)編譯器在運(yùn)行時(shí),對(duì)一些代碼上要求同步,但是被檢測(cè)到不可能存在共享數(shù)據(jù)競(jìng)爭(zhēng)的鎖進(jìn)行消除。

鎖粗化

如果一系列的連續(xù)操作都對(duì)同一個(gè)對(duì)象反復(fù)加鎖和解鎖,甚至加鎖操作是出現(xiàn)在循環(huán)體中的,那即使沒(méi)有線程競(jìng)爭(zhēng),頻繁地進(jìn)行互斥同步操作也會(huì)導(dǎo)致不必要的性能損耗。
如果虛擬機(jī)探測(cè)到一串零碎的操作都對(duì)同一個(gè)對(duì)象加鎖,將會(huì)把加鎖同步的范圍粗化到整個(gè)操作序列的外部,這樣只需要加鎖一次就夠了。

輕量級(jí)鎖

在沒(méi)有多線程競(jìng)爭(zhēng)的前提下,減少傳統(tǒng)的重量級(jí)鎖使用操作系統(tǒng)互斥量產(chǎn)生的性能損耗。
適用場(chǎng)景:無(wú)實(shí)際競(jìng)爭(zhēng),多個(gè)線程交替使用鎖;允許短時(shí)間的鎖競(jìng)爭(zhēng)。

偏向鎖

偏向鎖用于減少無(wú)競(jìng)爭(zhēng)且只有一個(gè)線程使用鎖的情況下,使用輕量級(jí)鎖產(chǎn)生的性能消耗。輕量級(jí)鎖每次申請(qǐng)、釋放鎖都至少需要一次CAS,但偏向鎖只有初始化時(shí)需要一次CAS。
適用場(chǎng)景:無(wú)實(shí)際競(jìng)爭(zhēng),且將來(lái)只有第一個(gè)申請(qǐng)鎖的線程會(huì)使用鎖。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享JAVA虛擬機(jī)高效并發(fā)的案例分析內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問(wèn)題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!

網(wǎng)頁(yè)標(biāo)題:JAVA虛擬機(jī)高效并發(fā)的案例分析-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://muchs.cn/article26/dsepjg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、網(wǎng)站改版、軟件開(kāi)發(fā)、服務(wù)器托管、網(wǎng)站內(nèi)鏈、網(wǎng)站策劃

廣告

聲明:本網(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)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷(xiāo)型網(wǎng)站建設(shè)