最近一直在學(xué)習(xí)java內(nèi)存模型相關(guān)的知識內(nèi)容赌朋,學(xué)習(xí)后的總結(jié)才能更上一層樓。那么java內(nèi)存模型是干什么的豁陆?為什么需要他呢柑爸。
1,我們?yōu)槭裁葱枰狫MM
我們在使用java開發(fā)的業(yè)務(wù)場景中盒音,很多時(shí)候都會碰到并發(fā)的問題表鳍,在并發(fā)場景下,數(shù)據(jù)的安全就非常重要祥诽,那么我們?yōu)榱吮WC數(shù)據(jù)安全需要滿足三方面的特性:
- 原子性
原子性是指一個(gè)操作在執(zhí)行的過程中譬圣,要么完成,要么就不完成雄坪,不能說在執(zhí)行過程中還中斷一下后繼續(xù)運(yùn)行厘熟。在java中,為了保證原子性,對應(yīng)的關(guān)鍵字就是synchronized绳姨;- 可見性
可見性是指當(dāng)多個(gè)線程訪問同一個(gè)變量時(shí)登澜,一個(gè)線程修改了變量的值后,其他的線程能夠看到立即修改后的值飘庄。java當(dāng)中脑蠕,我們可以使用最多的volatile就是用來保證多線程操作時(shí)變量的可見性,除了volatile跪削,Java中的synchronized和final兩個(gè)關(guān)鍵字也可以實(shí)現(xiàn)可見性谴仙。;- 有序性
就是程序執(zhí)行的順序是按照我們代碼的先后順序進(jìn)行的碾盐。在執(zhí)行程序時(shí)晃跺,為了提高性能,編譯器和處理器會對指令做重排序廓旬,在Java中哼审,可以使用synchronized和volatile來保證多線程之間操作的有序性谐腰。volatile關(guān)鍵字會禁止指令重排孕豹。synchronized關(guān)鍵字保證同一時(shí)刻只允許一條線程操作。
JMM是一種規(guī)范十气,目的是解決由于多線程通過共享內(nèi)存進(jìn)行通信時(shí)励背,存在的本地內(nèi)存數(shù)據(jù)不一致、編譯器會對代碼指令重排序砸西、處理器會對代碼亂序執(zhí)行等帶來的問題叶眉。
java內(nèi)存模型(JMM)是什么:
Java內(nèi)存模型(Java Memory Model ,JMM),在java中線程之間的共享變量存儲在主內(nèi)存中(main memory)芹枷,每個(gè)線程都有一個(gè)私有的本地內(nèi)存(local memory)衅疙,本地內(nèi)存中存儲了該線程以讀/寫共享變量的副本。線程與線程之間不能直接訪問對方本地內(nèi)存中的變量副本鸳慈,只能通過主內(nèi)存來進(jìn)行數(shù)據(jù)通信饱溢。
JMM內(nèi)存模型原子操作有如下步驟,理解這些步驟可以讓我們更深刻的理解java的內(nèi)存模型走芋。
- read(讀燃ɡ伞),從主內(nèi)存中讀取數(shù)據(jù)
- load(載入)翁逞,將主內(nèi)存讀取到的數(shù)據(jù)載入到工作內(nèi)存中
- use (使用)肋杖,從工作內(nèi)存中讀取數(shù)據(jù)來計(jì)算
- assign(賦值),將計(jì)算好的值重新賦值到工作內(nèi)存中
- store(存儲)挖函,將工作內(nèi)存數(shù)據(jù)寫入主內(nèi)存
- write(寫入)状植,將store過去的變量值賦值給主內(nèi)存中的變量
- lock(鎖定),將主內(nèi)存變量加鎖,標(biāo)識為線程獨(dú)占狀態(tài)
- unlock(解鎖)浅萧,將主內(nèi)存變量解鎖逐沙,解鎖后其他線程可以鎖定該變量
JSR133給Java內(nèi)存模型定義以下一組happen-before規(guī)則,了解下面的規(guī)則可以方便我們理解操作內(nèi)存時(shí)的可見性問題
- 單線程規(guī)則:同一個(gè)線程中的每個(gè)操作都happens-before于出現(xiàn)在其后的任何一個(gè)操作洼畅。
- 對一個(gè)監(jiān)視器的解鎖操作happens-before于每一個(gè)后續(xù)對同一個(gè)監(jiān)視器的加鎖操作吩案。
- 對volatile字段的寫入操作happens-before于每一個(gè)后續(xù)的對同一個(gè)volatile字段的讀操作。
- Thread.start()的調(diào)用操作會happens-before于啟動(dòng)線程里面的操作帝簇。
- 一個(gè)線程中的所有操作都happens-before于其他線程成功返回在該線程上的join()調(diào)用后的所有操作徘郭。
- 一個(gè)對象構(gòu)造函數(shù)的結(jié)束操作happens-before與該對象的finalizer的開始操作。
- 傳遞性規(guī)則:如果A操作happens-before于B操作丧肴,而B操作happens-before與C操作残揉,那么A動(dòng)作happens-before于C操作。
通過本篇介紹芋浮,我們大致了解了JMM的具體作用抱环,那么java當(dāng)中具體給給我們提供了哪些方式來保證線程之間通信時(shí)數(shù)據(jù)的安全性,volatile和synchronized的使用就不得不提了纸巷,下一篇我們詳細(xì)介紹這兩個(gè)關(guān)鍵字的用法和區(qū)別镇草。