1. 程式人生 > >Java併發之volatile關鍵字

Java併發之volatile關鍵字

引言

說到多執行緒,我覺得我們最重要的是要理解一個臨界區概念。

舉個例子,一個班上1個女孩子(臨界區),49個男孩子(執行緒),男孩子的目標就是這一個女孩子,就是會有競爭關係(執行緒安全問題)。推廣到實際場景,例如對一個數相加或者相減等等情形,因為操作物件就只有一個,在多執行緒環境下,就會產生執行緒安全問題。理解臨界區概念,我們對多執行緒問題可以有一個好意識。

Jav記憶體模型(JMM)

談到多執行緒就應該瞭解一下Java記憶體模型(JMM)的抽象示意圖.下圖:

執行緒A和執行緒B執行的是時候,會去讀取共享變數(臨界區),然後各自拷貝一份回到自己的本地記憶體,執行後續操作。
JMM模型是一種規範,就像Java的介面一樣。JMM會涉及到三個問題:原子性,可見性,有序性。

所謂原子性。就是說一個執行緒的執行會不會被其他執行緒影響的。他是不可中斷的。舉個例子:

int i=1

這個語句在Jmm中就是原子性的。無論是一個執行緒執行還是多個執行緒執行這個語句,讀出來的i就是等於1。那什麼是非原子性呢,按道理如果Java的程式碼都是原子性,應該就不會有執行緒問題了啊。其實JMM這是規定某些語句是原子性罷了。舉個非原子性例子:

i ++;

這個操作就不是原子性的了。因為他就是包含了三個操作:第一讀取i的值,第二將i加上1,第三將結果賦值回來給i,更新i的值。
所謂可見性。可見性表示如果一個值線上程A修改了,執行緒B就會馬上知道這個結果。
所謂有序性。所謂有序性值的是語意的有序性。就是說程式碼順序可能會發生變化。因為有一個指令重排機制。所謂指令重排,他會改變程式碼執行順序,為了讓cpu執行效率更高。為了防止重排序出錯,JMM有個happen-before規則,這個規則限制了那些語句執行在前,那些語句執行在後。

Happen-before:
程式順序原則:一個執行緒內保證語義的序列性
volatile原則:volatile變數的寫發生在讀之前
鎖規則:先加鎖再解鎖
傳遞性:a先於b,b先於c,則a必定先於c
執行緒的start方法先於他的每一個操作
執行緒所有的操作先於執行緒的終結
物件的建構函式執行、結束先於finalize()方法。

volatile

進入正題,volatile可以保證變數(臨界區)的可見性以及有序性,但是不能保證原子性。舉個例子:

public class VolatileTest implements Runnable{
    private static VolatileTest volatileTest = new VolatileTest();
    private  static volatile int i= 0;
    public static void main(String[] args) throws InterruptedException {
        for (int j = 0; j < 20; j++) {
            Thread a = new Thread(new VolatileTest());
            Thread b = new Thread(new VolatileTest());
            a.start();b.start();
            a.join();b.join();
            System.out.print(i+"&&");
        }

    }
    
    @Override
    public void run() {
        for (int j = 0; j < 1000; j++) {
            i++;
        }
    }

}

// 輸出結果
// 2000&&4000&&5852&&7852&&9852&&11852&&13655&&15655&&17655&&19655&&21306     
//&&22566&&24566&&26189&&28189&&30189&&32189&&34189&&36189&&38089&&

有結果看到有問題,雖然i已經添加了volatile關鍵字,說明volatile關鍵字不能保證i++的原子性。

那什麼場景適合使用volatile關鍵字

  1. 輕量級的“讀-寫鎖”策略
private volatile int value;
public int getValue(){ return value;}
public synchronized void doubleValue(){ value = value*value; }

2.單例模式(雙檢查鎖機制

private volatile static Singleton instace;   
public static Singleton getInstance(){  // 沒有使用同步方法,而是同步方法塊
    //第一次null檢查 ,利用volatile的執行緒間可見性,不需要加鎖,效能提高    
    if(instance == null){            
        synchronized(Singleton.class) {    //鎖住類物件,阻塞其他執行緒
            //第二次null檢查,以保證不會建立重複的例項       
            if(instance == null){       
                instance = new Singleton(); // 禁止重排序
            }  
        }           
    }  
    return instance;

參考

《現代作業系統(第三版)中文版》
《實戰Java高併發程式設計》
《Java併發程式設計的藝術》

如果我的文章幫助到您,可以關注我的微信公眾號,第一時間分享文章給您

相關推薦

java併發----volatile關鍵字

一、volatile 在java中,volatile關鍵字解決的是變數在多個執行緒之間的可見性,一旦一個共享變數(類的成員變數、類的靜態成員變數)被volatile修飾之後,那麼就具備了兩層語義: (1)保證了不同執行緒對這個變數進行操作時的可見性,即一個執行緒修改了某個變數的值,這

Java併發volatile關鍵字

引言 說到多執行緒,我覺得我們最重要的是要理解一個臨界區概念。 舉個例子,一個班上1個女孩子(臨界區),49個男孩子(執行緒),男孩子的目標就是這一個女孩子,就是會有競爭關係(執行緒安全問題)。推廣到實際場景,例如對一個數相加或者相減等等情形,因為操作物件就只有一個,在多執行緒環境下,就會產生執行緒安全問

Java併發volatile關鍵字詳解

概述 volatile關鍵字可以說是Java虛擬機器提供的最輕量級的同步機制,但是它並不容易完全被正確、完整地理解,以至於許多程式設計師都習慣不去使用它,遇到需要處理多執行緒資料競爭問題的時候一律使用synchronized來進行同步。瞭解volatile變數的語義對了解多執

java併發程式設計:volatile關鍵字解析

volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程式中使用它往往會導致出人意料的結果。在Java 5之後,volatile關鍵字才得以重獲生機。 volatile關鍵字雖然從字面上理解起來比較

java併發程式設計 -volatile關鍵字

java語言提供了一種稍弱的同步機制,即volatile變數,用來確保將變數的更新操作通知到其他的執行緒。 當把變數宣告為volatile型別後,編譯器與執行時都會注意到這個變數是共享的,因此不會將該變數上的操作與其他記憶體操作一起重排序,volatile變

Java併發16:volatile關鍵字的兩種用法-一次性狀態標誌、雙重檢查單例模式

volatile關鍵字在之前的章節中多次提及: 本章主要就volatile關鍵字的兩種實際用法進行說明。 1.volatile概述 volatile,即易變的,在Java中標識一個變數是易變變數。 volatile可以看成輕量級的synchron

Java 併發程式設計 : volatile 關鍵字解析

volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程式中使用它往往會導致出人意料的結果。在Java 5之後,volatile關鍵字才得以重獲生機。 volatile關鍵字雖然從字面上理解起來比較簡單,但是要用好不是一件容易的事情。由於v

Java併發程式設計---volatile關鍵字與atomic原子類

一.Volatile關鍵字      1.1 概念            volatile關鍵字的主要作用是使變數在多個執行緒間可見    1.2 示例程式 package com.thread.

Java併發程式設計---volatile關鍵字解析

volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程式中使用它往往會導致出人意料的結果。在Java 5之後,volatile關鍵字才得以重獲生機。 volatile關鍵字雖然從字面上理解起來比較簡

Java 併發volatile 關鍵字解析

摘要:   在 Java 併發程式設計中,要想使併發程式能夠正確地執行,必須要保證三條原則,即:原子性、可見性和有序性。只要有一條原則沒有被保證,就有可能會導致程式執行不正確。volatile關鍵字 被用來保證可見性,即保證共享變數的記憶體可見性以解決快取一致

java併發程式設計-volatile關鍵字

volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程式中使用它往往會導致出人意料的結果。在Java 5之後,volatile關鍵字才得以重獲生機。 volatile關鍵字雖然從字面上理解起來比較簡單,但是要用好不是一件容易的事情。由

Java併發synchronized關鍵字和Lock介面

歡迎點贊閱讀,一同學習交流,有疑問請留言 。 GitHub上也有開源 JavaHouse,歡迎star 引用 當開發過程中,我們遇到併發問題。怎麼解決? 一種解決方式,簡單粗暴:上鎖。將千軍萬馬都給攔下來,只允許一個人過獨木橋。書面意思就是將並行的程式變成序列的程式。現實的鎖有門鎖、掛鎖和抽屜鎖等等。

Java併發synchronized關鍵字深度解析(一)

前言         近期研讀路神之絕世武學,徜徉於浩瀚無垠知識之海洋,偶有攫取吉光片羽,惶恐未領略其精髓即隱入歲月深處,遂急忙記錄一二,順備來日吹cow之談資。本小系列為併發之親兒子-獨臂狂俠synchronized專場。 一、使用場景     &

Java 併發程式設計 volatile 關鍵字

作用 保證不同執行緒對 volatile 修飾的變數進行操作時的可見性,即一個執行緒修改了某個變數的值,這新值對其他執行緒來說是立即可見的。 禁止進行指令重排序。 volatile 的可見性 public class Test_09 {

Java併發程式設計volatile關鍵字

volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程式中使用它往往會導致出人意料的結果。在Java 5之後,volatile關鍵字才得以重獲生機。   volatile關鍵字雖然從字面上理解起來比較簡單,但

Java並發編程volatile關鍵字解析

行程 als 實現機制 自己 內存 util 數字 輸出 操作類 volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程序中使用它往往會導致出人意料的結果。在Java 5之後,volatile關鍵字才得以重獲生機

Java多執行緒-併發synchronized 關鍵字

synchronized 關鍵字 答: 底層實現: 進入時,執行 monitorenter,將計數器 +1,釋放鎖 monitorexit 時,計數器 -1 當一個執行緒判斷到計數器為 0 時,則當前鎖空閒,可以佔用;反之,當前執行緒進入等待狀態 含義

Java多執行緒程式設計核心技術volatile關鍵字

volatile與死迴圈                 在64bit的JVM上以“-server”伺服器模式執行java執行緒類程式碼時,為了保證在該模式下保障執行緒執行的效率,執行緒會一直在私有堆疊

Java執行緒安全volatile關鍵字

一、前言 我們知道在多執行緒的場景下,執行緒安全是必須要著重考慮的。Java語言包含兩種內在的同步機制:同步塊(synchronize關鍵字)和 volatile 變數。但是其中 Volatile 變數雖然使用簡單,有時候開銷也比較低,但是同時它的同步性較差,

java多執行緒volatile關鍵字

在java執行緒併發處理中,關鍵字volatile的主要作用是使變數在多個執行緒間可見。那麼volatile到底該怎麼用了?我們首先來看一段程式碼: public class MyThread1 i