緩存一致性與可見性


緩存一致性與可見性

什么樣的數據會存入緩存?

編譯器或CPU可以明確知曉的,可能被經常訪問的數據。例如一個在循環體中的變量,因為這個變量需要經常訪問,如果每次都從主存中拿,那就太慢了。

緩存一致,是跟誰一致?

是跟主存一致,當主存中的對應數據發生變動的時候,CPU中的緩存也會隨之變動。例如Cache中緩存了變量x的值,當主存中的x的值變動的時候,Cache中的值也會刷新。“刷新”可能是將該值標記為“失效”,下次需要時從主存拉取,或是直接用新值覆蓋。

主存的數據變動是如何被監聽到的?

Bus Snooping。總線窺探,只要監聽總線操作就可知道其他CPU對主存的訪問情況。例如監聽到x變量的寫操作,那就表明x變量的值有變動。

高速緩存一致這些操作誰來實現?

底層硬件實現,現代計算機都有提供此功能。

那這樣是不是已經有了可見性?

沒有,當然如果可見性指的是“當主存值發生變化的時候,Cache可以看到”,那確實是實現了。問題是可見性不是這么定義的,它說的是“當一個線程對一個變量進行修改時,其他線程都能夠看到”。

這兩種表述方式有什么不同?

其實就是“一個線程對變量A的修改” ≠ “主存值發生變化”。也就說,修改變量的值后,修改的只是緩存中的值,不會馬上寫入主存。

為什么不馬上寫入主存?

因為慢。所以這個寫操作會被重排序到后面,這個操作還是會執行的,只是優先級沒那么高。

那是不是馬上寫入主存就能實現可見性呢?

是的,只要馬上寫入主存,由於底層提供“高速緩存一致性”,所以當內存中的變量發生變更時,其他CPU的緩存也會隨之更新。那這樣可見性就有了。

那么如何讓它馬上寫入主存呢?

防止重排序就可以了,這樣寫入內存的操作就會被立即執行。一般就是加內存屏障。synchronized、volatile都依賴內存屏障。

什么時候需要可見性?

正常的程序變量一般都不需要可見性。除非這個變量可能被多個線程同時訪問,且你需要用這個變量來協調線程操作。那這時候這個變量才需要具有可見性。這時候如果不保證可見性,就很可能出現奇怪的問題,即有時可以正確執行,有時又不行。為什么呢?因為有時候,這些線程剛好在同一CPU上執行,訪問的是同一個Cache,自然就能得到正確的,也就是最新的值。但是,大多數情況不是這樣,多個線程會在多個CPU上執行,如果不保證可見性,就可能得到過期的值。然后你就會很奇怪,明明看日志打印,已經改了啊,為什么其他線程還是沒反應過來呢?

插一句

其實緩存一致性和可見性的問題,都是由多CPU的引發的,就是因為每個CPU都有一個Cache,所以才有了這一堆的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM