Java 關鍵字-volatile

volatile 介紹

volatile 是 Java 提供的一種輕量級的同步機制。Java 語言包含兩種內在的同步機制:同步塊或者說同步方法和 volatile 變量,相比於 synchronized 重量級鎖,volatile 更輕量級,因爲它不會引起線程上下文的切換和調度。但是 volatile 變量的同步性較差,而且其使用也更容易出錯。

volatile 保證可見性,不保證原子性

可見性

當要給線程寫 volatile 變量時,JMM 會把該線程本地內存中的變量立即刷新到主內存中去,這個操作會導致其他線程中的 volatile 變量緩存無效。

原子性

一個變量被 volatile 修飾,兩個線程都想對這個變量修改,都獲取了最新的值,對其進行自增操作也就是 i++,i++ 的過程可以分爲三步,首先獲取 i 的值,其次對值進行加 1,最後將得到的新值寫會到緩存中。那麼最後的結果是增加了 1,而不是正確的 2。所以,如果一個變量被 volatile 修飾了,那麼肯定可以保證每次讀取這個變量值的時候得到的值是最新的,但是一旦需要對變量進行自增這樣的非原子操作,就不會保證這個變量的原子性了。

總結

Java 中只有對基本類型變量的賦值和讀取是原子操作,如 i = 1 的賦值操作,但是像 j = i 這樣的操作都不是原子操作,因爲進行了多次原子操作,比如先讀取 i 的值,再將 i 的值賦值給 j,兩個原子操作加起來就不是原子操作了。

指令重排

重排序是指編譯器和處理器爲了優化程序性能而對指令序列進行排序的一種手段。重排序需要遵守一定規則:
1、重排序操作不會對存在數據依賴關係的操作進行重排序。
2、重排序是爲了優化性能,但是不管怎麼重排序,單線程下程序的執行結果不能被改變。

volatile 禁止指令重排

若用volatile修飾共享變量,在編譯時,會在指令序列中插入內存屏障來禁止特定類型的處理器重排序,volatile禁止指令重排序也有一些規則:執行到 volatile 變量時,其前面的所有語句都執行完,後面所有語句都未執行。且前面語句的結果對 volatile 變量及其後面語句可見。

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