1. 程式人生 > >如何正確使用volatile變數

如何正確使用volatile變數

Java 語言中的 volatile 變數可以被看作是一種 “程度較輕的 synchronized”;與 synchronized 塊相比,volatile 變數所需的編碼較少,並且執行時開銷也較少,但是它所能實現的功能也僅是 synchronized 的一部分。本文介紹了幾種有效使用 volatile 變數的模式,並強調了幾種不適合使用 volatile 變數的情形。

鎖提供了兩種主要特性:互斥(mutual exclusion) 和可見性(visibility)。互斥即一次只允許一個執行緒持有某個特定的鎖,因此可使用該特性實現對共享資料的協調訪問協議,這樣,一次就只有一個執行緒能夠使用該共享資料。可見性要更加複雜一些,它必須確保釋放鎖之前對共享資料做出的更改對於隨後獲得該鎖的另一個執行緒是可見的 —— 如果沒有同步機制提供的這種可見性保證,執行緒看到的共享變數可能是修改前的值或不一致的值,這將引發許多嚴重問題。

Volatile 變數

Volatile 變數具有 synchronized 的可見性特性,但是不具備原子特性。這就是說執行緒能夠自動發現 volatile 變數的最新值。Volatile 變數可用於提供執行緒安全,但是隻能應用於非常有限的一組用例:多個變數之間或者某個變數的當前值與修改後值之間沒有約束。因此,單獨使用 volatile 還不足以實現計數器、互斥鎖或任何具有與多個變數相關的不變式(Invariants)的類(例如 “start <=end”)。

出於簡易性或可伸縮性的考慮,您可能傾向於使用 volatile 變數而不是鎖。當使用 volatile 變數而非鎖時,某些習慣用法(idiom)更加易於編碼和閱讀。此外,volatile 變數不會像鎖那樣造成執行緒阻塞,因此也很少造成可伸縮性問題。在某些情況下,如果讀操作遠遠大於寫操作,volatile 變數還可以提供優於鎖的效能優勢。

正確使用 volatile 變數的條件

您只能在有限的一些情形下使用 volatile 變數替代鎖。要使 volatile 變數提供理想的執行緒安全,必須同時滿足下面兩個條件:

1. 對變數的寫操作不依賴於當前值。
2. 該變數沒有包含在具有其他變數的不變式中。

對這兩個條件的驗證可以參見下面兩篇部落格:

相關推薦

java 正確使用 Volatile 變數

轉自:https://www.ibm.com/developerworks/cn/java/j-jtp06197.html   Java 語言中的 volatile 變數可以被看作是一種 “程度較輕的 synchronized”;與 synchronized&n

如何正確使用volatile變數

Java 語言中的 volatile 變數可以被看作是一種 “程度較輕的 synchronized”;與 synchronized 塊相比,volatile 變數所需的編碼較少,並且執行時開銷也較少,但是它所能實現的功能也僅是 synchronized 的一部分

Java理論與實踐:正確使用volatile變數

之所以將這種技術稱之為“開銷較低的讀-寫鎖”是因為您使用了不同的同步機制進行讀寫操作。因為本例中的寫操作違反了使用volatile的第一個條件,因此不能使用volatile安全地實現計數器——您必須使用鎖。然而,您可以在讀操作中使用volatile確保當前值的可見性,因此可以使用鎖進行所有變化的操作,使用vo

Java 理論與實踐: 正確使用 Volatile 變數(轉)

Java 語言中的 volatile 變數可以被看作是一種 “程度較輕的 synchronized”;與synchronized 塊相比,volatile 變數所需的編碼較少,並且執行時開銷也較少,但是它所能實現的功能也僅是 synchronized 的一部分。本文介紹了幾

Java併發程式設計(5):volatile變數修飾符-意料之外的問題(含程式碼)

volatile用處說明在JDK1.2之前,Java的記憶體模型實現總是從主存(即共享記憶體)讀取變數,是不需要進行特別的注意的。而隨著JVM的成熟和優化,現在在多執行緒環境下volatile關鍵字的使用變得非常重要。 在當前的Java記憶體模型下,執行緒可以把變數儲存在本地記憶體(比如機器的暫存器)中,而

AbstractQueuedSynchronizer--基於CAS自旋volatile變數插入尾節點

private transient volatile Node tail; private Node enq(final Node node) { for (;;) { Node t = tail;

併發程式設計——為什麼volatile變數++操作執行緒不安全

學習volatile的時候也許我們會看到下面這句話: 對於volatile變數來說,自增操作執行緒不安全。   那為什麼不安全呢?本帥博主看的是《併發程式設計的藝術》這本書,這本書對這一事件也沒有做出很讓人易懂的解釋。那麼我們自己用例子

volatile變數記憶體可見性的原理分析—彙編指令分析

在java虛擬機器的記憶體模型中,有主記憶體和工作記憶體的概念,每個執行緒對應一個工作記憶體,並共享主記憶體的資料,下面看看操作普通變數和volatile變數有什麼不同: 1、對於普通變數:讀操作會優先讀取工作記憶體的資料,如果工作記憶體中不存在,則從主記憶體中

多執行緒讀書筆記二(java記憶體模型、volatile變數、記憶體模型與synchronized、CAS)

java記憶體模型 java中,執行緒之間的通訊是通過共享記憶體的方式,儲存在堆中的例項域,靜態域以及陣列元素都可以線上程間通訊。java記憶體模型控制一個執行緒對共享變數的改變何時對另一個執行緒可見。 執行緒間的共享變數存在主記憶體中,而對於每一個執行緒,都有一個私有的工

從快取行出發理解volatile變數、偽共享False sharing、disruptor

volatile關鍵字 當變數被某個執行緒A修改值之後,其它執行緒比如B若讀取此變數的話,立刻可以看到原來執行緒A修改後的值 注:普通變數與volatile變數的區別是volatile的特殊規則保證了新值能立即同步到主記憶體,以及每次使用前可以立即從記憶體重新整理,

Java多執行緒中的volatile變數

首先,volatile的作用是保證記憶體的可見性,但是不能保證操作的原子性。 在Java中記憶體模型中,將記憶體模型分為主記憶體和工作記憶體。 主記憶體是對所有執行緒所共享的,而每個執行緒都有自己的工作記憶體(比如cpu快取,暫存器等等都是一個原理的,都是為了加快讀取速度),工作記憶

Java多執行緒之volatile變數

Java 語言中的 volatile 變數可以被看作是一種 “程度較輕的 synchronized”;與 synchronized 塊相比,volatile 變數所需的編碼較少,並且執行時開銷也較少,但是它所能實現的功能也僅是 synchronized 的一部分。本文介紹了幾種有效使用 volati

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

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

java volatile變數及其使用場景

java中的一種稍弱的同步機制,就是volatile變數,用於確保將變數的更新操作通知到其他執行緒。 變數宣告為volatile後: (1)編譯器與執行時都會注意到這個變數是共享的,因此不會將該變數上的操作與其他記憶體操作一起重排序(重排序不懂的,可以自行百度,需要理解)

深入理解Java虛擬機器筆記---volatile變數的特殊規則

   當一個變數定義成volatile之後,它將具備兩種特性:第一是保證此變數對所有執行緒的可見性,這裡的“可見性”是指當一條執行緒修改了這個變數的值,新值對於其它執行緒是可以立即得知的,變數值線上程間傳遞均需要通過主記憶體來完成,如:執行緒A修改一個普通變數的值,然後向主

JAVA併發程式設計之Volatile變數

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

const和volatile變數是否可以同時修飾一個變數

問題:const和volatile是否可以同時修飾一個變數?有什麼含義? 答案:如果一個變數不會被本程式改變,通常可能給它加上const,但如果該變數可能被其他程式改變而本程式又在檢測這個變數的值,就需要給它加上volatile,於是變數就同時有volatile和const

Java併發程式設計-volatile變數

  併發程式設計時,Java 的volatile提供了一種弱的執行緒同步機制。 volatile提供了兩種語義:   1)禁止編譯器對其修飾的程式碼進行重組   2)將變數的寫操作立即同步到記憶體中而

volatile變數型別的詳細說明

關鍵字volatile是java虛擬機器提供的最輕量級的同步機制。但是許多人對它的理解還是不正確,不完整。 下面詳細講解一下: 由於關鍵字volatile關鍵沒有被更好的理解,因此許多程式設計師遇到處理多執行緒資料競爭問題的時候都是有synchronzied來同步,僅為讀寫

【Java併發程式設計】之五:volatile變數修飾符—意料之外的問題(含程式碼)

示例程式 下面給出一段程式碼,通過其執行結果來說明使用關鍵字volatile產生的差異,但實際上遇到了意料之外的問題: public class Volatile extends Object implements Runnable { //value變數沒有被標記為volatile private