1. 程式人生 > >Java 基礎系列之volatile變數(一)

Java 基礎系列之volatile變數(一)

一、鎖
  兩種特性:互斥性(mutual exclusion)、可見性(visibility)、原子性(atomic)
  互斥性就是一次只有一個執行緒可以訪問該共享資料,可見性就是釋放鎖之前,對共享資料的修改,隨後獲取鎖的另一個執行緒是可見的,也就是說一個執行緒修改了共享變數的值,另一個執行緒訪問該共享變數的時候能立即得到最新修改的值。原子性就是多個變數或者某個變數的當前值和修改值之間存在某種一定約束。

二、volatile
  volatile變數具有可見性,但不具有原子性。這就是說執行緒能夠自動發現votatile變數的最新值。如果想讓volatile變數提供執行緒安全,這我們必須滿足該變數滿足下面2個特性。另一方面,volatile變數可以防止該變數操作的指令重排和優化。
  第一、對於volatile變數的寫操作不能依賴於該變數的當前值,比如volatile修飾變數x,而變數x操作:x++。如果多個執行緒操作x++,並不能達到預期的結果,原因在於x++這個操作是:首先cpu從記憶體中讀取變數x的值到cpu的一級cache中,接著cpu對cache中的值做修改,最後把cache中修改的值回寫到記憶體中。這一組操作需要以原子性的方式執行,才能保證執行緒安全,但是volatile本身不滿足原子性。
  第二、該volatile變數沒有在具有其他變數的不變式中,比如2個volatile變數start和end,而 start<=end這個語句在多執行緒中可能出現執行緒安全問題。
三、效能


  一般情況下使用volatile變數的同步機子的效能要優於鎖,就是說,在目前大多數的處理器架構上,volatile讀操作開銷非常低 —— 幾乎和非volatile讀操作一樣。而 volatile寫操作的開銷要比非volatile寫操作多很多,因為要保證可見性需要實現記憶體界定(Memory Fence),即便如此,volatile 的總開銷仍然要比鎖獲取低。
四、運用
  在使用volatile的時候,需要記住該變數的狀態獨立於程式其他內容時,才能使用volatile變數。如下是幾個運用:
  1、狀態標誌。比如volatile變數isInitialized是一個boolean型別,用於表示某種操作是否已經初始化完成。
  2、一次性安全釋出
  3、獨立觀察
  4、開銷較低的讀-寫鎖策略
五、總結

  如果一個變數被volatile修飾,那麼cpu在讀取該變數的時候都不會從cpu本身的cache快取中讀取,而是每次從記憶體中讀取,這樣保證了每個volatile變數的可見性。但是volatile變數不滿足原子性。更加說明一下x++的不是執行緒安全的。比如多個執行緒操作volatile變數x進行x++.其中x初始值是0,執行緒A和執行緒B都從記憶體中讀取x到各自的cache中,如cacheA(x=0),和cacheB(x=0),此時2個執行緒各自在自己的cache中操作變數x,這時執行緒A的cache值為cacheA(x=1),執行緒B的cache值為cacheB(x=1)。由於變數x是volatile型別,所以執行緒會把修改變數x的值立即回寫到記憶體中。比如執行緒A立即回寫,則變數x的值在記憶體中為1,而後執行緒B也回寫,則變數x的值為1。這跟預期的結果有差距的。

相關推薦

Java 基礎系列volatile變數()

一、鎖   兩種特性:互斥性(mutual exclusion)、可見性(visibility)、原子性(atomic)  互斥性就是一次只有一個執行緒可以訪問該共享資料,可見性就是釋放鎖之前,對共享資料的修改,隨後獲取鎖的另一個執行緒是可見的,也就是說一個執行緒修改了共享變數的值,另一個執行緒訪問該共享

Java 基礎系列volatile變量()

釋放 pos clu 每次 修改 mil 可見 family 依賴 一、鎖   兩種特性:互斥性(mutual exclusion)、可見性(visibility)、原子性(atomic)  互斥性就是一次只有一個線程可以訪問該共享數據,可見性就是釋放鎖之前,對共享數據

幹貨:Java並發編程系列volatile

並發編程 程序員 Java 架構 volatil Java語言規範第三版中對volatile的定義如下:Java編程語言允許線程訪問共享變量,為了確保共享變量能被準確和一致地更新,線程應該確保通過排他鎖單獨獲得這個變量。了解volatile關鍵字之前需要先了解下Java內存模型,java內

Java基礎系列(四十):集合List

前言 List是繼承自Collection的一個子介面,它提供了一個有序的集合,在這個集合中我們可以使用索引去獲取集合中的值,同時,我們也可以通過迭代器去訪問集合中的元素,第一種方法被稱為隨機訪問,因為我們可以按照任意的順序去訪問元素,而使用迭代器就必須順序的去訪問元素。 結構圖

JAVA 基礎系列 重排序和Volatile

重排序 在執行程式時,編輯器和處理器會對指令進行重排序,重排序分為: 編譯器重排序:在不改變程式碼語義的情況下,優化效能而改變了程式碼執行順序; 指令並行的重排序:處理器採用並行技術使多條指令重疊執行,在不存在資料依賴的情況下,改變機器指令的執行順序; 記憶體

Java基礎系列基礎數據類型

四種 分數 系列 數字 好處 java基礎 bsp style 情況 在Java中,一共有8種基本類型,其中有四種整型,兩種浮點型,還有一個表示unicode編碼的字符單元的字符類型char和1種用於表示真假值的boolean類型。 在這裏介紹一下有種在項目比較常用

JAVA基礎學習路(

個人理解 整形 之路 boolean mman 類型 布爾 屬性 註釋 JAVA基礎概念: PATHl: path屬於操作系統的屬性,是系統用來搜尋可執行文件的路徑,個人理解是類似於linux中的全局變量 CALSSPATH:java程序解釋類文件時加載文件的路徑 註釋

Java基礎系列(三十):異常

為什麼有異常機制 假如在一個Java程式執行期間出現了一個錯誤,這個錯誤可能是由於檔案包含了錯誤的資訊,或者由於網路連接出現超時,或者就因為使用了無效的陣列下標,或者試圖使用一個沒有賦值的物件(null)造成的。 當這些錯誤出現的時候,我們希望程式可以返回到一種安全的狀態或者允許

JAVA併發程式設計Volatile變數

volatile:不穩定的;爆炸性的;反覆無常的volatile變數是java提供的一種弱同步機制(我覺得只能確保讀取的同步),當把變數宣告為volatile型別後:            1.編譯器與執行時都會注意到這個變數是共享的,會變的,不會將該變數上的操作與其他記憶體

java基礎系列ConcurrentHashMap源碼分析(基於jdk1.8)

threshold 主存 類比 tile num method 過程 參數 nsf 1、前提   在閱讀這篇博客之前,希望你對HashMap已經是有所理解的;另外你對java的cas操作也是有一定了解的,因為在這個類中大量使用到了cas相關的操作來保證線程安全的。   

死磕 java同步系列volatile解析

問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實現原理? (4)volatile的缺陷? 簡介 volatile可以說是Java虛擬機器提供的最輕量級的同步機制了,但是它並不容易被正確地理解,以至於很多人不習慣使用它,遇到多執行緒問題一律

Java 系列Filter(

_id java ted img 3.2 認證 nts index.jsp enc 一、過濾器   過濾器就是在源數據和目的數據之間起過濾作用的中間組件。它可以截取客戶端和資源之間的請求和響應信息,並且對這些信息進行過濾。    二、應用場景   1、對用戶請求進行統一認證

Java基礎系列--集合ArrayList

邏輯結構 完全 必須 () abs 數組使用 就會 而已 自減 原創作品,可以轉載,但是請標註出處地址:http://www.cnblogs.com/V1haoge/p/8494618.html 一、概述   ArrayList是Java集合體系中最常使用,也是最簡單的集

Java基礎-SSMmybatis多對關聯關系

轉載 bat ont -s 否則 tis 聲明 ron 作品             Java基礎-SSM之mybatis多對一關聯關系                                     作者:尹正傑 版權聲明:原創作品,謝絕轉載!否則將追究法律責任。

Java基礎系列

java的基本型別與包裝類 1、java是純面向物件的語言,但是為了方便還是提供了8種基本的資料型別,基本資料型別的資料不具備“物件”的特性——沒有屬性、沒有方法。同時為了滿足其面向物件的特點,Java為每種基本資料型別分別設計了對應的類,稱為包裝類,並且為其新增一些實用的方法。 基本型

Java基礎常量、變數、運算子

資料型別 : Java中的基本型別功能簡單,不具備物件的特性,為了使基本型別具備物件的特性,所以出現了包裝類,就可以像操作物件一樣操作基本型別資料。 基本型別對應的包裝類 基本型別 byte int short long float double boolean char 包裝型別

java基礎學習小知識點篇

java基礎學習之小知識點 1.程式碼塊 分類 2.super和this的注意點 3.過載(overload)和重寫(override) 4.final修飾符 final指的是**最終的**。 注意點:

Java基礎系列(四十五):集合Map

簡介 Map是一個介面,代表的是將鍵對映到值的物件。一個對映不能包含重複的鍵,每個鍵最多隻能對映到一個值。 Map 介面提供了三種collection檢視,允許以鍵集、值集或鍵-值對映關係集的形式檢視某個對映的內容。對映順序 定義為迭代器在對映的 collection 檢視上返回

Java基礎系列(四十四):集合ArrayList

簡介 ArrayList與Vector非常相似,他們都是基於陣列實現的集合,都可以動態擴容,只不過Vector是同步的,所需的資源較多,而且比較老,有一些缺點,所以我們現在更多的是去使用ArrayList,而不是Vector。下面,我們在閱讀原始碼的過程中遇到的一些問題對ArrayL

Java基礎系列(四十三):集合Vector&Stack

Vector 簡介 Vector是一種實現了動態陣列的集合,何為動態陣列呢?即長度可以自動增長的陣列,它是執行緒同步的,也就是說同一時刻只有一個執行緒可以寫Vector,可以避免多執行緒同時寫引起的不一致性,但是比較消耗資源。接下來,我們來看Vector的原始碼。 原始碼