您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Java內(nèi)存模型與線程分別是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Java內(nèi)存模型與線程分別是什么”吧!
1、Amdahl定律:通過系統(tǒng)中并行化與串行化的比重來描述多處理器系統(tǒng)能獲得的運(yùn)算加速能力;摩爾定律:用于描述處理器晶體管數(shù)量與運(yùn)行效率之間的發(fā)展關(guān)系。并發(fā)處理的廣泛應(yīng)用是使得Amdahl定律代替摩爾定律成為計(jì)算機(jī)性能發(fā)展源動(dòng)力的根本原因,也是人類壓榨計(jì)算機(jī)運(yùn)算能力的最有力武器。
2、衡量一個(gè)服務(wù)性能的高低好壞,每秒事務(wù)處理數(shù)(Transaction Per Second,TPS)是最重要的指標(biāo)之一,它代表著一秒內(nèi)服務(wù)端平均能響應(yīng)的請(qǐng)求總數(shù),而TPS值與程序的并發(fā)能力又有著非常密切的關(guān)系。
3、 1)為什么要有高速緩存?解決處理器和內(nèi)存的速度矛盾——存儲(chǔ)設(shè)備與處理器的運(yùn)算速度差幾個(gè)數(shù)量級(jí)。但是引入新的問題:緩存一致性。
2)如何解決緩存一致性?需要各個(gè)處理器在訪問緩存時(shí)都遵循一些協(xié)議,如:MSI、MESI、MOSI、S有那配色、Firefly及Dragon Protocol等。
3)什么是亂序執(zhí)行優(yōu)化?處理器對(duì)輸入代碼進(jìn)行亂序執(zhí)行,計(jì)算后將亂序執(zhí)行的結(jié)果重組,保證該結(jié)果與順序執(zhí)行的結(jié)果一致,但不保證程序中各個(gè)語句計(jì)算的先后順序與輸入代碼中的順序一致。Java虛擬機(jī)的即時(shí)編譯也有類似的指令重排優(yōu)化。
4、內(nèi)存模型,可以理解為在特定的操作協(xié)議下,對(duì)特定的內(nèi)存或高速緩存進(jìn)行讀寫訪問的過程抽象。
5、JSR:Java Specification Requests,Java規(guī)范提案。
6、Java內(nèi)存模型的主要目標(biāo)是定義程序中各個(gè)變量的訪問規(guī)則。此處變量包括實(shí)例字段、靜態(tài)字段和構(gòu)成數(shù)組對(duì)象的元素,但不包括局部變量與方法參數(shù),因?yàn)楹笳呤蔷€程私有的,不會(huì)被共享。
7、Java內(nèi)存模型規(guī)定了所有的變量都存儲(chǔ)在主內(nèi)存(Main Memory)中,每條線程還有自己的工作內(nèi)存(Working Memory),線程的工作內(nèi)存中保存了被該線程使用到的變量的主內(nèi)存的副本拷貝,線程對(duì)變量的所有操作都必須在工作內(nèi)存中進(jìn)行,而不能直接讀寫主內(nèi)存中的變量。不同的線程之間也無法直接訪問對(duì)方工作內(nèi)存中的變量,線程間變量值的傳遞均需要通過主內(nèi)存來完成。這里的主內(nèi)存和工作內(nèi)存與Java內(nèi)存區(qū)域中的堆、棧、方法區(qū)等并不是同一個(gè)層次的內(nèi)存劃分,這兩者基本上是沒有關(guān)系的。
8、Java內(nèi)存模型定義了8種操作來完成主內(nèi)存與工作內(nèi)存的交互,虛擬機(jī)實(shí)現(xiàn)時(shí)必須保證每種操作都是原子的、不可再分的。lock、unlock、read、load、use、assign、store、write。Java內(nèi)存模型還規(guī)定了在執(zhí)行上述8種基本操作時(shí)必須滿足的規(guī)則。通過這8中基本的內(nèi)存訪問操作和規(guī)則就已經(jīng)完全確定了Java程序中哪些內(nèi)存訪問操作在并發(fā)下是安全的。因?yàn)槎x嚴(yán)謹(jǐn),實(shí)踐起來麻煩,可以采用先行發(fā)生原則來確定一個(gè)訪問在并發(fā)環(huán)境下是否安全。
9、關(guān)于volatile型變量的特殊規(guī)則:
1)Java虛擬機(jī)提供的最輕量級(jí)的同步機(jī)制;
2)被volatile修改的變量將具備兩個(gè)特性:
第一是保證變量對(duì)所有線程的可見性,但不保證原子性;
第二是禁止指令重排,
3)原理:通過設(shè)置內(nèi)存屏障,即一個(gè)lock前綴的空操作,它會(huì)將本CPU的Cache寫入內(nèi)存,且該寫入操作會(huì)將別的CPU或別的內(nèi)核無效化其Cache,從而達(dá)到讓volatile變量的修改對(duì)其它CPU立即可見,volatile屏蔽指令重排語義在JDK1.5中才被完全修復(fù)。
4)Java內(nèi)存模型對(duì)volatile變量定義的特殊規(guī)則:a.使用前先取值;b.修改后立即同步;c.不會(huì)被指令重排;
5)除了volatile,Java還有兩個(gè)關(guān)鍵字能夠?qū)崿F(xiàn)可見性,即synchronized和final。
10、Java內(nèi)存模型是圍繞著在并發(fā)過程中如何處理原子性、可見性和有序性這三個(gè)特征來建立的。
11、先行發(fā)生原則
1)它是判斷數(shù)據(jù)是否存在競(jìng)爭(zhēng)、線程是否安全的主要依據(jù),依靠這個(gè)原則,我們可以通過幾條規(guī)則一攬子解決并發(fā)環(huán)境下兩個(gè)操作之間是否可能存在沖突的所有問題。
2)Java內(nèi)存模型下一些“天然的”發(fā)生關(guān)系,這些先行發(fā)生關(guān)系無須借助任何同步器協(xié)助就已經(jīng)存在:
a)程序次序規(guī)則。準(zhǔn)確的說是控制流順序而不是程序代碼順序;
b)管程鎖定規(guī)則。對(duì)同一個(gè)鎖,unlock先行發(fā)生于lock操作;
c)volatile變量規(guī)則。對(duì)于volatile變量,寫操作先行發(fā)生于讀操作;
d)線程啟動(dòng)規(guī)則。Thread的start方法先行發(fā)生于此線程的每一個(gè)動(dòng)作;
e)線程終止規(guī)則。線程的所有操作都先行發(fā)生于對(duì)此線程的終止檢測(cè);
f)線程中斷規(guī)則。對(duì)線程interrupt方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測(cè)到中斷事件的發(fā)生;就是說
g)對(duì)象終結(jié)規(guī)則。一個(gè)對(duì)象的初始化完成先行發(fā)生于它的finalize方法的開始。
h)傳遞性。A先于B,B先于C,則A先于C。
3)時(shí)間先后順序與先行發(fā)生原則之間基本沒有太大的關(guān)系,所以我們衡量并發(fā)安全問題的時(shí)候不要受到時(shí)間順序的干擾,一切必須以先行發(fā)生原則為準(zhǔn)。
12、線程的實(shí)現(xiàn)
1)線程是比進(jìn)程更輕量級(jí)的調(diào)度執(zhí)行單位,線程引入可以把一個(gè)進(jìn)程的資源分配和調(diào)度分開,各個(gè)線程既共享進(jìn)程資源,又可以獨(dú)立調(diào)度;
2)在JavaAPI中,一個(gè)native方法往往意味著這個(gè)方法沒有使用或無法使用平臺(tái)無關(guān)的手段來實(shí)現(xiàn);
3)實(shí)現(xiàn)線程的三種方式:使用內(nèi)核線程實(shí)現(xiàn)、使用用戶線程實(shí)現(xiàn)、使用用戶線程加輕量級(jí)進(jìn)程混合實(shí)現(xiàn)。
4)使用內(nèi)核線程實(shí)現(xiàn):
a)內(nèi)核線程是直接由操作系統(tǒng)內(nèi)核支持的線程;
b)程序一般不會(huì)直接去使用內(nèi)核線程,而是使用內(nèi)核線程的一種高級(jí)接口——輕量級(jí)進(jìn)程(Light Weight Process, LWP),輕量級(jí)進(jìn)程與內(nèi)核線程之間是1:1的關(guān)系,因此稱為一對(duì)一線程模型;
c)各種線程操作都需要系統(tǒng)調(diào)用,需要在用戶態(tài)和內(nèi)核態(tài)中來回切換,代價(jià)較高,另外每個(gè)輕量級(jí)進(jìn)程都需要有一個(gè) 內(nèi)核線程支持,要消耗一定的內(nèi)核資源;
5)使用用戶線程實(shí)現(xiàn):
a)這種線程不需要切換到內(nèi)核態(tài),因此操作可以非常快速且低消耗,也可以支持規(guī)模更大的線程數(shù)量;
b)這種進(jìn)程與用戶線程之間1:N的關(guān)系稱為一對(duì)多線程模型;
c)實(shí)現(xiàn)比較復(fù)雜。
6)使用用戶線程加輕量級(jí)進(jìn)程混合實(shí)現(xiàn):用戶線程與輕量級(jí)進(jìn)程的數(shù)量比是不定的,因此這種N:M的關(guān)系稱為多對(duì)多線程模型;
7)Java線程的實(shí)現(xiàn):Windows平臺(tái)和Linux平臺(tái)使用一對(duì)一線程模型實(shí)現(xiàn),Solaris平臺(tái),提供了專有的虛擬機(jī)參數(shù)來指定虛擬機(jī)使用哪種線程模型。
13、Java線程調(diào)度:
1)線程調(diào)度是指系統(tǒng)為線程分配處理器使用權(quán)的過程,主要有兩種方式:協(xié)同式調(diào)度和搶占式調(diào)度。
2)Java使用的線程調(diào)度方式是搶占式調(diào)度。
3)Java一共設(shè)置了10個(gè)級(jí)別的線程優(yōu)先級(jí)(Thread.MIN_PRIORITY和Thread.MAX_PRIORITY),在兩個(gè)線程同時(shí)處于Ready狀態(tài)時(shí),優(yōu)先級(jí)越高的線程越容易被系統(tǒng)選擇執(zhí)行。但是線程優(yōu)先級(jí)不太靠譜,不能太依賴優(yōu)先級(jí)。
14、狀態(tài)轉(zhuǎn)換。Java語言定義了五種線程狀態(tài),一個(gè)線程只能有且只有其中的一種狀態(tài):
New:創(chuàng)建后尚未啟動(dòng);
Runnable:有可能正在執(zhí)行,也可能在等待CPU分配執(zhí)行時(shí)間;
Waiting:線程不會(huì)被分配CPU執(zhí)行時(shí)間,需要被其它線程顯式地喚醒。
Timed Waiting:線程不會(huì)被分配CPU執(zhí)行時(shí)間,不過不需要被其它線程顯式地喚醒,在一定時(shí)間后會(huì)由系統(tǒng)自動(dòng)喚醒;
Blocked:等待鎖釋放;
Terminated:線程已終止。
15、Java語言中各種操作共享的數(shù)據(jù)分類5類:不可變、絕對(duì)線程安全、相對(duì)線程安全、線程兼容和線程對(duì)立。相對(duì)線程安全就是我們通常意義上所講的線程安全,單獨(dú)操作是線程安全的,但涉及到一定順序的連續(xù)執(zhí)行,需要同步手段保證線程安全。
16、線程安全的實(shí)現(xiàn)方法:
1)互斥同步
a)同步是指在多線程并發(fā)訪問共享數(shù)據(jù)時(shí),保證共享數(shù)據(jù)在同一時(shí)刻只被一個(gè)線程使用;
b)最基本的同步手段就是synchronized。有兩點(diǎn)要特別注意:首先synchronized對(duì)同一個(gè)線程是可重入的,其次同步塊在已進(jìn)入的線程執(zhí)行完之前,會(huì)阻塞后面其它線程的進(jìn)入,而Java線程是映射到操作系統(tǒng)的原生線程之上的,如果要阻塞或喚醒一個(gè)線程,都需要操作系統(tǒng)幫忙完成,這就需要從用戶態(tài)切換到內(nèi)核態(tài),因此狀態(tài)轉(zhuǎn)換需要耗費(fèi)很多處理器時(shí)間;
c)還可以用java.util.concurrent保重的重入鎖(ReentrantLock)來實(shí)現(xiàn)同步。相比synchronized,ReentrantLock提供了一些高級(jí)功能;
d)JDK1.6或以上,性能因素就不再是選擇ReentrantLock的理由了,虛擬機(jī)在未來的性能改進(jìn)中也會(huì)更偏向與synchronized;
e)互斥同步是一種悲觀的并發(fā)策略;
2)非阻塞同步 :樂觀的并發(fā)策略,不需要把線程掛起
3)無同步方案:
a)保證線程安全,并不是一定就要進(jìn)行同步,兩者沒有因果關(guān)系。
b)可重入代碼:天生就是線程安全的。
c)線程本地存儲(chǔ):ThreadLocal,每個(gè)線程的Thread對(duì)象中都有一個(gè)ThreadLocalMap對(duì)象,這個(gè)對(duì)象存儲(chǔ)了一組以ThreadLocal.threadLocalHashCode為鍵,以本地線程變量為值的K-V值對(duì),ThreadLocal對(duì)象就是當(dāng)前線程的ThreadLocalMap的訪問入口,每個(gè)ThreadLocal對(duì)象都包含了一個(gè)獨(dú)一無二的threadLocalHashCode值,使用這個(gè)值就可以在線程K-V值對(duì)中找回對(duì)應(yīng)的本地線程變量。
17、鎖優(yōu)化技術(shù):適應(yīng)性自旋,鎖消除、鎖粗化、輕量級(jí)鎖、偏向鎖
到此,相信大家對(duì)“Java內(nèi)存模型與線程分別是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。