volatile關鍵字的一些個人見解(持續更新,初版)

一、線程的通信方式
在JMM中,每個線程都有自己的工作內存、總線上又有一個主內存(共享內存)。假設線程A要對對象object進行操作,那麼首先會將object對象從主內存裏讀取到工作內存,在工作內存中進行修改,修改完成後再同步到主內存,這樣其他線程就可以通過主內存讀取到線程A對對象的修改。但是這種工作模式存在一個問題,就是如果線程A在工作內存中對object對象進行了修改,但是還沒有將其同步到主內存,線程B這個時候在主內存讀取object的值就是線程A修改前的值,也就是線程A對object的修改線程B不可見,這就造成了線程安全問題。
在這裏插入圖片描述
二、volatile關鍵字
爲了解決這種不可見的安全問題,人們設置了volatile關鍵字。
在早期凡是加上這個關鍵字的對象,在執行對其操作的方法時,均會在java代碼轉換成彙編語言時在操作的語言段前面加上LOCK#標記,帶有此標記的操作會直接將總線上的主內存鎖住,在操作完成並寫入主內存前其他線程均無法操作主內存。這種方式雖然解決了可見性的問題,但是容易造成阻塞,效率比較低下。
後來爲了解決效率的問題,人們就設置了緩存一致性協議,比如Intel 的MESI協議,MESI協議保證了每個緩存中使用的共享變量的副本是一致的。它核心的思想是:當CPU寫數據時,如果發現操作的變量是共享變量,即在其他CPU中也存在該變量的副本,會發出信號通知其他CPU將該變量的緩存行置爲無效狀態,因此當其他CPU需要讀取這個變量時,發現自己緩存中緩存該變量的緩存行是無效的,那麼它就會從內存重新讀取。
三、併發編程的三大要素
原子性:即一個操作或者多個操作 要麼全部執行並且執行的過程不會被任何因素打斷,要麼就都不執行。同步鎖主要解決的就是原子性的問題,它通過對對象加鎖,使同一時間只有一個線程能對對象進行操作,避免了多線程同時操作造成結果與預期不符的情況。但是同步鎖限制了加鎖方式和訪問方式,因此人們又增加了LOCK對象進行更加精細的操作。
可見性:是指當多個線程訪問同一個變量時,一個線程修改了這個變量的值,其他線程能夠立即看得到修改的值。主要通過volatile關鍵字進行實現。
有序性:即程序執行的順序按照代碼的先後順序執行。在cpu執行代碼時爲了提升執行效率,往往會對執行代碼進行重排序,重排序又分爲編譯器重排序和處理器重排序,還涉及到屏障限制的問題,本人還沒理清楚哈,以後再說。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章