久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Java內(nèi)存模型和volatile關(guān)鍵字怎么掌握

163次閱讀
沒有評論

共計 2210 個字符,預(yù)計需要花費(fèi) 6 分鐘才能閱讀完成。

這篇文章主要講解了“Java 內(nèi)存模型和 volatile 關(guān)鍵字怎么掌握”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Java 內(nèi)存模型和 volatile 關(guān)鍵字怎么掌握”吧!

java 內(nèi)存模型(JMM):

相關(guān)概念:1)在命令式編程中,線程之間的通信機(jī)制有兩種:共享內(nèi)存和消息傳遞。2)java 的并發(fā)采用的是共享內(nèi)存模型:通過讀 / 寫內(nèi)存中的公共狀態(tài)進(jìn)行隱式通信。概念:java 線程之間的通信是由 java 內(nèi)存模型控制的,JMM 決定一個線程對共享變量的寫入何時對另一個線程可見。1 線程之間的共享變量存儲在主內(nèi)存中,每個線程都有一個私有的工作內(nèi)存,工作內(nèi)存中存儲了該線程讀 / 寫共享變量的副本。2 工作內(nèi)存是 JMM 的一個抽象概念,并不真實(shí)存在。它涵蓋了緩存、寫緩沖區(qū)、寄存器以及其他的硬件和編譯器優(yōu)化。3 線程對變量的所有操作 (讀取、賦值等) 都必須在工作內(nèi)存中進(jìn)行,而不能直接讀寫主內(nèi)存中的變量。4 不同的線程之間也無法直接訪問對方工作內(nèi)存中的變量,線程間變量值的傳遞均需要通過主內(nèi)存來完成。

volatile 關(guān)鍵字:

相關(guān)概念:
 緩存行:緩存器中可以分配的最小存儲單位。L1 緩存:內(nèi)部緩存。L2 緩存:外部緩存。1)為了提高處理速度,處理器不直接和內(nèi)存進(jìn)行通信,而是先將系統(tǒng)內(nèi)存中的數(shù)據(jù)讀到緩存 (L1、L2) 后再進(jìn)行操作,但操作完成后,處理器是不知道何時要把操作后的數(shù)據(jù)寫回到內(nèi)存中。2)對 volatile 修飾的變量進(jìn)行寫操作時,JVM 會向處理器發(fā)送一條 Lock 前綴的指令,將這個變量所在緩存行 (即 JMM 中的工作內(nèi)存) 的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存中,并且將其它 CPU 里緩存了該內(nèi)存地址的數(shù)據(jù)無效。1 對 volatile 修飾的變量進(jìn)行寫操作 (賦值) 時,在 JIT 編譯器生成的匯編指令中,我們會發(fā)現(xiàn)有一個以 Lock 為前綴的指令。2 以 Lock 為前綴的指令在多核處理器下會引發(fā)了兩件事情:①將當(dāng)前處理器緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存中  ②這個寫回內(nèi)存的操作會導(dǎo)致其它 CPU 里緩存了該內(nèi)存地址的數(shù)據(jù)無效。volatile 的內(nèi)存原語:當(dāng)讀一個 volatile 變量時,JMM 會把該線程對應(yīng)的工作內(nèi)存置為無效,線程接下來將從主內(nèi)存中讀取共享變量。當(dāng)寫一個 volatile 變量時,JMM 會把該線程對應(yīng)的工作內(nèi)存中的共享變量值刷新到主內(nèi)存。1 將本地內(nèi)存中的數(shù)據(jù)設(shè)置為無效, 
 2 從主內(nèi)存中將數(shù)據(jù)復(fù)制到本地內(nèi)存中, 
 3 在本地內(nèi)存中進(jìn)行操作, 
 4 操作完成后將本地內(nèi)存中的數(shù)據(jù)刷新到主內(nèi)存中。整體看起來就像是直接在主內(nèi)存中操作一樣。 

用 volatile 修飾的變量如果被一個線程更改了,那么其它的線程都會立即感知,并且每個線程獲取該變量的值都是最新的值,訪問 volatile 修飾的變量看起來就像是直接在內(nèi)存中讀寫一樣。可見性:對一個 volatile 變量的讀,(任意線程)總是能看到對這個 volatile 變量最后的寫入。原子性:對一個 volatile 變量的讀 / 寫具有原子性,但類似于 volatile++ 這種復(fù)合操作不具有原子性。不會引起線程上下文的切換
volatile 與 synchronized 的比較:1)關(guān)鍵字 volatile 只能修飾變量,synchronized 可以修飾代碼塊、方法 2)volatile 不能保證原子性,synchronized 保證原子性:volatile 可以保證數(shù)據(jù)的可見性,但是不能保證原子性,所以 volatile 解決的是變量在多線程之間的可見性;synchronized 可以保證原子性,也保證了可見性(synchronized 會將私有內(nèi)存和公共內(nèi)存中的數(shù)據(jù)做同步),所以 synchronized 解決的是多線程之間訪問資源的同步性。

重排序:

說明:在執(zhí)行程序時,為了提高性能,編譯器和處理器常常會對指令做重排序。重排序分 2 種類型:1)編譯器重排序:編譯器在不改變單線程程序語義的前提下,可以重新安排語句的執(zhí)行順序。2)處理器重排序:1 指令級并行的重排序:現(xiàn)代處理器采用了指令級并行技術(shù)來將多條指令重疊執(zhí)行。如果不存在數(shù)據(jù)依賴性,處理器可以改變語句對應(yīng)機(jī)器指令的執(zhí)行順序。2 內(nèi)存系統(tǒng)的重排序:  由于處理器使用緩存和讀 / 寫緩沖區(qū),這使得加載和存儲操作看上去可能是在亂序執(zhí)行。
兩個操作間重排序的條件:1 當(dāng)?shù)谝粋€操作是 volatile 讀,不管第二個操作是什么,都不能重排序。這個規(guī)則確保 volatile 讀之后的操作不會被編譯器重排序到 volatile 讀之前。2 當(dāng)?shù)诙€操作是 volatile 寫,不管第一個操作是什么,都不能重排序。這個規(guī)則確保 volatile 寫之前的操作不會被編譯器重排序到 volatile 寫之后。3 當(dāng)?shù)谝粋€操作是 volatile 寫,第二個操作是 volatile 讀時,不能重排序。由以上 3 點(diǎn)可以得出結(jié)論:兩個 volatile 變量操作不能夠進(jìn)行重排序。2)為了實(shí)現(xiàn) volatile 的內(nèi)存語義,編譯器在生成字節(jié)碼時,會在指令序列中插入內(nèi)存屏障來禁止特定類型的處理器重排序。(內(nèi)存屏障:將前面操作的共享變量值刷新到主內(nèi)存中。)

感謝各位的閱讀,以上就是“Java 內(nèi)存模型和 volatile 關(guān)鍵字怎么掌握”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對 Java 內(nèi)存模型和 volatile 關(guān)鍵字怎么掌握這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-16發(fā)表,共計2210字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 梅州市| 无极县| 望都县| 平顺县| 洛南县| 涟水县| 涡阳县| 惠州市| 海淀区| 武定县| 四平市| 武强县| 宾川县| 宜春市| 湖北省| 青龙| 仁化县| 城固县| 孟村| 田林县| 江城| 杂多县| 五家渠市| 淮北市| 衡山县| 淅川县| 布尔津县| 鄂州市| 平谷区| 教育| 广河县| 调兵山市| 四川省| 房产| 山西省| 大兴区| 凉山| 德令哈市| 根河市| 临城县| 喀什市|