java中volatile的簡單理解
原創作品,可以轉載,但是請標註出處地址:http://www.cnblogs.com/V1haoge/p/7833881.html
據說,volatile是java語言中最輕量級的並發控制方式。
volatile可以保證變量的可見性,指的是什麽呢?
可見性指的是在某一線程中對變量進行修改之後,其他線程可以立即發現並使用這個修改(一個線程的修改對其他線程可見)。
可見性的實現方式:volatile對java內存模型中主內存和工作內存交互方式的控制。volatile確保一個線程對其修飾的變量的更改立即寫入到主內存,同時確保每一次針對其修飾變量的讀取操作直接從主內存中獲取(即volatile強制將assign賦值操作和store、write操作綁定在一起,將use使用操作強制和read、load操作綁定在一起,這樣assign之後必須執行store、write操作,use操作之前必須先執行read、load操作)這樣就確保了其他線程讀取到的變量的值是最新的(不熟悉這幾個操作的同學請先了解java內存模型)。
註意:volatile可以實現可見性,但是無法實現原子操作。原子操作是與java代碼相關的,並不是這麽一個關鍵字既可以控制得了的。(請將可見性和原子操作區分開來,我之前就混淆在一起,分開之後立即通透了)
java中實現原子操作的方式還是有很多的,但是並不包含volatile,簡單的實現方式有:atomic包下的原子操作(通過CAS實現),基本數據類型的讀寫操作等。
java中經典的非原子操作如自增實現,普通的i++操作看似只有一句話,但是編譯成機器指令之後擁有多少行,不可知,坑頂不是一句就能實現的,這麽多命令要執行當然無法保證原子性,這時候我們可以AtomicInteger和AtomicLong原子操作類的getAndIncrement()方法來實現。
volatile的另一個作用就是避免重排序,使用內存屏障的方式來實現禁止重排序。在單線程環境中當然沒有必要禁止重排序,但是在多線程環境中重排序後執行的代碼就可能會出錯,比如線程A中需要檢測線程B中的某一個變量的值,如果沒有使用volatile修飾該變量,線程B中針對這個變量的操作就可能會發生重排序,可能會提前執行,這是一旦操作執行,那麽線程A就可以會提前得到這個變量的值(或許是在一些線程A的準備工作還未全部準備好的情況,假設這些準備工作在線程B中定義,但是與變量操作無依賴關系,一旦變量操作提前,這些準備工作就會滯後,這是線程A就會在準備工作尚未完成的情況下啟動執行後行代碼,導致出錯)。為變量加上volatile修飾之後,就會禁止其操作的重排序,保證所以的準備工作全部執行完成之後在進行變量操作,然後線程A在準備齊備的情況啟動,得以正常執行。
java中volatile的簡單理解