volidate與可見性

volidate是java中用來保證併發訪問同一狀態的可見性的一種工具。可見性是指一個線程對內存中某一地址的值修改一定能對其餘訪問該地址的線程生效。聽起來是個理所固然的事,但這簡單的事背後卻有一套複雜的機制來保證。其複雜機制產生的緣由是在cpu和內存間加入緩存所致使的,緩存協調了CPU和內存間效率不一致的問題,但引入了內存不可見的問題。cpu訪問內存時,一次性將內存中的一頁讀到緩存中,再從緩存中讀取指定地址的值用於操做,若是當某一個cpu修改了某地址的狀態的同時又有另外一個cpu同時也對該地址進行讀或者寫,可想而知在兩個緩存中同一地址的值極可能是不一樣的,那麼哪一個緩存中的值應該被寫回內存中呢?凡事講個先來後到,因此cpu先寫回的緩存應該寫回內存,而另外一個緩存的值將變爲無效。這種機制經過mesi協議來保證,mesi表明了緩存的四種狀態,每一個緩存監聽其餘緩存的狀態變化,據此改變自身的狀態。E表明該地址被cpu獨佔,沒有其餘cpu的緩存有該地址;而當另外一個cpu也要訪問該地址時,以前的cpu該地址緩存狀態變爲s,同時新來的cpu的該緩存地址狀態也是s,因此s表示該地址共享;若是兩個cpu中的一個對該地址進行寫操做,那麼這一個cpu的該地址狀態就變爲m,而另外一個cpu的緩存中該地址將變爲i,因此m就表明修改,i表明無效。被修改的地址的值應該被寫回內存中,但這個效率和cpu的運行效率相比很是慢,若是cpu等待地址對應的值寫回內存,什麼事都不幹就太浪費了,因此就先不寫回內存。但修改的值確定必定必須寫回內存,那麼就引入了storeBuffers和無效隊列這兩個組件。cpu對地址的值寫再也不直接寫入緩存而是storebuffers中,cpu可當即往下執行。storebuffers在某一時刻向無效隊列寫入消息,當即得到響應,而無效隊列按隊列順序設置緩存中的地址狀態爲無效。那麼問題就來了,由於改變的狀態沒有同步更新,其餘cpu可能在別的cpu改寫地址的值時去讀取地址的值,這就產生了狀態不一致的問題。硬件上沒法肯定哪一個操做應該優先,因此提供memorry barrier給軟件來控制操做的前後。java中volidate就是用來表示memorry barrier,當對volidate修飾的變量賦值時那麼編譯器會添加一個write memorry barrier,其做用是將緩存中的狀態寫回內存;當對volidate修飾的變量賦值時那麼編譯器會添加一個read memory barrier,其做用是強制讀內存中狀態java

相關文章
相關標籤/搜索