并發(fā)--總結
MESI和高速緩存
硬件再單核時代為了提高cpu的使用率所以在主內(nèi)存和cpu之間加入了高速緩存,這樣的好處是cpu可以快速對數(shù)據(jù)進行指令操作。
當多核時代到來由于每個核心都有自己的高速緩存,但是又共享主內(nèi)存。這就會導致各個處理器之間的緩存數(shù)據(jù)不一致。為了解決緩存不一致的情況
出現(xiàn)了許多的緩存一致性協(xié)議,比較熟悉的就是MESI協(xié)議。雖然緩存一致性協(xié)議解決了共享變量一致性問題,但是因為其性能較差,所以又引入了寫緩沖
和無效隊列。這個引入也會導致共享變量一致性問題和偽重排序問題。為了解決一致性和真?zhèn)沃嘏判騿栴},各個硬件又開始支持了內(nèi)存屏障,雖然實現(xiàn)細節(jié)有所不同
但是大致是相似的。
JMM
說回JMM,java為了屏蔽各個硬件和操作系統(tǒng)訪問內(nèi)存的差異(類似于接口,規(guī)定了內(nèi)存模型和訪問規(guī)則,各個JVM團隊在不同的硬件和操作系統(tǒng)上實現(xiàn)即可,細節(jié)可以不一樣)
整個內(nèi)存模型借鑒了我們之前說的cpu和主內(nèi)存之間的操作,java 也規(guī)定了自己的主內(nèi)存(是jvm的主內(nèi)存,也屬于os內(nèi)存的一部分),同時還有各個工作內(nèi)存(類似于高速緩存),各個線程類似于處理器。
而java提供的voliatile和synchronized 底層都是依托內(nèi)存屏障,讓指令不會重排序同時又可以讓讀寫操作按照指令順序正常執(zhí)行完畢。
JAVA規(guī)定了內(nèi)存間交互操作
- 1.規(guī)定了java工作內(nèi)存和主內(nèi)存的交互規(guī)則
內(nèi)存交互必須滿足的規(guī)則
- 1.確定了一些原則 其中對lock和unlock操作時候會需要對變量 進行的值進行更新和同步這就需要內(nèi)存屏障
HappenBefore
- 1.通過該規(guī)則避免了內(nèi)存模型中所有的有序性都只靠volatile和synchronized完成
對象頭
CAS
- 1.依靠lock信號來實現(xiàn),雖然不是內(nèi)存屏障但是又mfence的語義
- 2.因為還需要額外鎖住總線和緩存上鎖,成本更高。
流程如下:
- 1.對總線和緩存上鎖
- 2.強制所有l(wèi)ock信號前的指令都執(zhí)行完畢,并同步完成相關緩存
- 3.執(zhí)行l(wèi)ock后指令
- 4.釋放總線和緩存上的鎖
- 5.強制所有l(wèi)ock信號后的指令都在此之后被執(zhí)行并同步相關緩存。
As-If-Serial
- 1.不管怎么重排序(編譯器和處理器為了提高并行度),(單線程)程序的執(zhí)行結果不能被改變
- 2.為了遵守as-if-serial語義,編譯器和處理器不會對存在數(shù)據(jù)依賴關系的操作做重排序
mfence和sfence
mfence
- 1.全能屏障
sfence
- 1.保證sfence之前的store執(zhí)行完畢再執(zhí)行sfence指令之后的store執(zhí)行
- 2.不影響load命令的亂序
- 3.StoreStore Barriers
lfence
- 1.LoadLoad Barriers。
final
- 1.依靠sfence