java基礎之volatile關鍵字

2020-12-08 暖爸的java家園

Volatile

Java語言的關鍵字,用來聲明變量,表示這個變量是被同時運行的幾個線程修改的,需要保證變量的可見性並禁止指令重排序。

可見性的含義:

可見性的意思是指當一個線程修改一個共享變量時,另外一個線程能讀到這個修改後的值,volatile作用就是當一個線程修改了共享變量的值,其他線程馬上就能知道。

Java內存模型規定所有的變量都是存在主存當中,每個線程都有自己的工作內存。線程對變量的所有操作都必須在工作內存中進行,而不能直接對主存進行操作。並且每個線程不能訪問其他線程的工作內存

那麼Volatile是如何來保證可見性的呢?

在x86處理器下通過工具生成的彙編指令來看看對Volatile進行寫操作時,CPU會做什麼事兒:

Java代碼:

instance = new Singleton();//其中instance是volatile修飾的變量

彙編代碼:

0x01a3de1d: movb $0×0,0×1104800(%esi);

0x01a3de24: lock addl $0×0,(%esp);

lock前綴指令實際上相當於一個內存屏障,會提供3個功能:

1.它確保指令重排序時不會把其後面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的後面;即在執行到內存屏障這句指令時,在它前面的操作已經全部完成;

2.它會強制將對緩存的修改操作立即寫入主存;

3.如果是寫操作,它會導致其他CPU中對應的緩存行無效。

處理器為了提高處理速度,不直接和內存進行通訊,而是先將系統內存的數據讀到內部緩存,後再進行操作,但操作完之後不知道何時會寫到內存,如下圖1所示:

圖1

如果對聲明了Volatile變量進行寫操作,JVM就會向處理器發送一條Lock前綴的指令,將這個變量所在緩存行的數據寫回到系統內存。

但是就算寫回到內存,如果其他處理器緩存的值還是舊的,所以在多處理器下,為了保證各個處理器的緩存是一致的,硬體層面就會實現緩存一致性協議(每個處理器通過嗅探在總線上傳播的數據來檢查自己緩存的值是不是已經不是最新的,當處理器發現自己緩存行對應的內存地址被修改,就會將當前處理器的緩存行設置成無效狀態),線程再處理該數據時,就會強制重新從內存裡把數據讀到處理器緩存裡,如圖2。

圖2

指令重排序:

請看如下代碼:

x = 1; //語句1

y = 1; //語句2

flag = true; //語句3

x = x+1; //語句4

y = y-1; //語句5

在執行過程中,編譯器可能會自行安排執行順序,讓語句執行的更快。

在單線程情況下,編譯器能保證語句4在語句1之後,語句5在語句2之後,因為兩者之間有依賴關係,而結果是可以確定的。

在多線程時,因為多個緩存和線程同時處理,就難以保證結果了,可能語句4排在語句1之前執行,導致結果變化。而設置flag為Volatile類型的參數,那麼在多線程情況下,語句4也一定在語句1之後,語句5在語句2之後,重排序只存在語句4和5,語句1和語句2之間,不能跨越語句3進行重排序

相關焦點

  • 你應該要理解的java並發關鍵字volatile
    提高java的並發編程,就不得不提volatile關鍵字,不管是在面試還是實際開發中 volatile都是一個應該掌握的技能。他的重要性不言而喻。因此也有必要學好。一、為什麼要用到volatile關鍵字?
  • Java內存模型與volatile關鍵字
    Java的內存模型大概樣子還是有必要了解下的,今天就學習了下,順便學習了一點volatile關鍵字!關鍵字volatile一個變量如果被volatile修飾那麼他有兩個特性:1、變量對所有線程的可見性,意思是如果一條線程修改了這個變量的值,那麼其他線程就可以立刻知道的。
  • 1分鐘讀懂java中的volatile關鍵字
    本文將以儘量簡潔的方式介紹java中的volatile關鍵字。如果覺得寫的不錯,記得,如果寫的不好歡迎批評指正,讓我們一起進步!1.volatile簡介先來看volatile這個單詞的本義:說簡單點,volatile就是表示某人或某物是不穩定的、易變的。
  • Java裡面volatile關鍵字修飾引用變量的陷阱
    Java裡面volatile關鍵字修飾引用變量的陷阱如果我現在問你volatile的關鍵字的作用,你可能會回答對於一個線程修改的變量對其他的線程立即可見。嚴謹的回答應該是volatile關鍵字對於基本類型的修改可以在隨後對多個線程的讀保持一致,但是對於引用類型如數組,實體bean,僅僅保證引用的可見性,但並不保證引用內容的可見性。
  • Java中volatile關鍵字概覽
    一、第一章 volatile關鍵字概覽多線程下變量的不可見性概述在多線程並發執行下,多個線程修改共享的成員變量,會出現一個線程修改了共享變量的值後,另一個線程不能直接 看到該線程修改後的變量的最新值。JMM(Java Memory Model):Java內存模型,是java虛擬機規範中所定義的一種內存模型,Java內存模型是標準化的,屏蔽掉了底層不同計算機的區別。
  • Java並發之volatile關鍵字內存可見性問題
    Java並發之volatile關鍵字內存可見性問題線程之間數據共享案例我們先來看一個場景:Main函數啟動後,調用一個線程向list中添加數據。這裡就是我們今天需要講解的關鍵字:volatile。【ps:還有其他方案可以解決,如同步鎖】Volatile關鍵字Volatile中文意思:易變的;不穩定的Volatile關鍵字是一種類型修飾符,用它來聲明的變量表示不可以別編譯器未知因素更改。
  • volatile關鍵字詳解
    點擊上方藍色字體,選擇「標星公眾號」優質文章,第一時間送達  作者 |  Zzzkis來源 |  urlify.cn/AVVFNr76套java;    }}class Mythread{    //不加volatile,主線程無法得知num的值發生了改變,從而陷入死循環    volatile int num = 0;    public void increment(){        ++num;    }}
  • 知名公司面試題:談談你對volatile關鍵字的理解
    作為一名java程式設計師,求職面試時,關於volatile關鍵字時常會遇到。張工最近到某知名網際網路公司面試,面試官提出這樣的一個問題:談談你對volatile關鍵字的理解張工一時間沒有回答上來,面試官:你都工作三年了,怎麼對volatile關鍵字都沒掌握啊。
  • Java並發編程之驗證volatile的可見性
    Java並發編程之驗證volatile的可見性通過系列文章的學習,凱哥已經介紹了volatile的三大特性。1:保證可見性 2:不保證原子性 3:保證順序。那麼怎麼來驗證可見性呢?本文凱哥將通過代碼演示來證明volatile的可見性。
  • Java並發編程徹底搞懂volatile關鍵字
    關鍵字進行來詳解。本篇文章主要對volatile關鍵字進行解剖。解決辦法是使用volatile關鍵字。關鍵字volatile的作用是強制從公共堆棧中取得變量的值,而不是從線程私有數據棧中取得變量值。對於volatile修飾的變量,JVM虛擬機只是保證從主內存加載到線程工作內存的值是最新的;因此volatile關鍵字解決的是變量【讀】時的可見性問題,但無法保證原子性,對於多個線程訪問同一個實例變量時需要進行【加鎖】同步。
  • 就是要你懂 Java 中 volatile 關鍵字實現原理
    前言我們知道volatile關鍵字的作用是保證變量在多線程之間的可見性,它是java.util.concurrent包的核心,沒有volatile就沒有這麼多的並發類給我們使用本文詳細解讀一下volatile關鍵字如何保證變量在多線程之間的可見性,在此之前,有必要講解一下CPU緩存的相關知識,掌握這部分知識一定會讓我們更好地理解volatile的原理,從而更好、更正確地地使用volatile關鍵字。
  • Java中 volatile 關鍵字的最全總結,趕快給自己查缺補漏吧!
    事實上就是保證操作是原子性操作,才能保證使用volatile關鍵字的程序在並發時能夠正確執行。使用volatile關鍵字修飾共享變量便可以禁止這種重排序。3.採用java並發包中的原子操作類,原子操作類是通過CAS循環的方式來保證其原子性的
  • 深度解析volatile關鍵字,就是這麼簡單
    .dylib關鍵字volatile是Java虛擬機提供的最輕量級的同步機制,當一個變量被關鍵字volatile修飾之後,它有如下兩個特性:保證了這個變量對所有線程的可見性禁止指令重排序優化關鍵字volatile可以保證變量對所有線程的可見性,也就是當一個線程修改了這個變量的值,其他線程能夠立即得到修改的值。
  • 教學筆記:這樣來學習Java volatile關鍵字
    相信大多數Java程式設計師都學習過volatile這個關鍵字的用法。百度百科上對volatile的定義:volatile是一個類型修飾符(type specifier),被設計用來修飾被不同線程訪問和修改的變量。volatile的作用是作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值。
  • java並發編程之volatile關鍵字
    >例如結果如果不設置stop變量為volatile,並不意味著程序一定不會結束因為這個stop變量的刷新操作也需要看cpu的處理方式但是加上volatile一定不會出現問題2、防止重排序單例中的雙重檢查加鎖示例demo為什麼要將singleton 設置為volatile呢?
  • Java程式設計師面試必備:Volatile全方位解析
    前言volatile是Java程式設計師必備的基礎,也是面試官非常喜歡問的一個話題,本文跟大家一起開啟vlatile學習之旅,如果有不正確的地方,也麻煩大家指出哈,一起相互學習~1.volatile的用法 2.vlatile變量的作用 3.現代計算機的內存模型(計算機模型
  • Java中volatile特性概述
    volatile特性概述volatile總體概覽在上節中,我們已經研究完了volatile可以實現並發下共享變量的可見性,除了volatile可以保證可見性外,volatile 還具備如下一些突出的特性:volatile的原子性問題:volatile
  • C語言中volatile關鍵字的使用
    打開APP C語言中volatile關鍵字的使用 發表於 2018-03-17 11:55:00 volatile的意思是易變的
  • 什麼時候需要使用volatile關鍵字
    想必大家平時都見過volatile關鍵字,可是大家知道什麼時候需要使用volatile關鍵字嗎?這裡為了產生預期的行為,需要阻止編譯器做這種優化,可以使用volatile關鍵字修飾。volatile int a = 100;volatile關鍵字和const關鍵字相對應,const關鍵字告訴編譯器其修飾的變量是只讀的,編譯器根據只讀屬性做一些操作,而volatile關鍵字告訴編譯器其修飾的變量是易變的,同理編譯器根據易變屬性也會做一些操作。它會確保修飾的變量每次都讀操作都從內存裡讀取,每次寫操作都將值寫到內存裡。
  • Java Volatile關鍵字分析(二)
    下面是沒有使用Volatile的代碼示例 如上代碼所示定義的counter共享計數器對象,並沒有使用volatile ,synchronize這樣的關鍵,在對共享對象進行多線程讀寫的情況下,是無法保證一致性性和準確性的。因為在讀寫操作時,先是對本地緩存進行操作的。如下圖所示: