在講volatile關鍵字之前我們先了解Java的內存模型,Java內存模型規定所有的變量都是存在主存當中,每個線程都有自己的工作內存。線程對變量的所有操作都必須在自己的工作內存中進行,而不能直接對主存進行操作。各線程間的工作內存互不干擾。
談一下你對 volatile 關鍵字的理解?( volatile 的作用是什么?)
答:volatile 是 Java 虛擬機提供的最輕量級的同步機制。當變量被定義成 volatile 之后,具備兩種特性:
(1)保證對變量操作的可見性.
(2)禁止指令重排序優化.
注意:不保證原子性
怎么理解原子性,可見性和指令重排?
原子性:程序中的所有操作是不可中斷的,要么全部執行成功要么全部執行失敗。
可見性:指當多個線程訪問同一個變量時,如果其中一個線程修改了這個變量的值,其他線程能夠立即看得到修改的值。
指令重排:為了提高程序運行效率,可能會對輸入指令進行重新排序,即程序中各個語句的執行先后順序同代碼中的順序不一定一致。(但是它會保證單線程程序最終執行結果和代碼順序執行的結果是一致的)
可見性,指令重排實例:
https://www.cnblogs.com/qdhxhz/p/9179725.html
哪些地方用到過volatile?
1、單例模式(雙重檢驗鎖DCL)
菜鳥教程--https://www.runoob.com/design-pattern/singleton-pattern.html
2、讀寫鎖手寫緩存
3、CAS JUC包中大量使用volatile
volatile底層的實現機制?
如果把加入volatile關鍵字的代碼和未加入volatile關鍵字的代碼都生成匯編代碼,會發現加入volatile關鍵字的代碼會多出一個lock前綴指令。
lock前綴指令實際相當於一個內存屏障,內存屏障提供了以下功能:
1 . 重排序時不能把后面的指令重排序到內存屏障之前的位置
2 . 使得本CPU的Cache寫入主存
3 . 寫入動作也會引起別的CPU或者別的內核無效化其Cache,相當於讓新寫入的值對別的線程可見。
Synchronized與volatile區別
(1) synchronized即保證了數據的可見性也保證了原子性,volatile能保證對變量操作的可見性,但不能完全保證原子性。比如,i++ 如果使用 synchronized 修飾是線程安全的,而 volatile 會有線程安全的問題。
(2) volatile只能修飾變量,synchronized可以修飾變量,方法以及代碼塊。
(3) volatile在多線程中不會存在阻塞問題,synchronized會存在阻塞問題。
(4) volatile解決的是多個線程之間對變量操作的可見性,而synchroized解決的是多個線程之間訪問資源的同步性。
參考
面試官必問的8道volatile關鍵字命題,你答對了嗎?
https://blog.csdn.net/l18848956739/article/details/88660353
進行重新排序