1. 程式人生 > >真正理解volatile關鍵字

真正理解volatile關鍵字

volatile的作用

1,保證可見性

2,保證cpu指令順序執行

上面兩個特性就不過多解釋了

當volatile 修飾 int i 時,為什麼不是執行緒安全呢?

如圖:

由上,我們可以得出以下結論。

  1. read和load階段:從主存複製變數到當前執行緒工作記憶體;
  2. use和assign階段:執行程式碼,改變共享變數值;
  3. store和write階段:用工作記憶體資料重新整理主存對應變數的值。

       在多執行緒環境中,use和assign是多次出現的,但這一操作並不是原子性,也就是在read和load之後,如果主記憶體count變數發生修改之後,執行緒工作記憶體中的值由於已經載入,不會產生對應的變化,也就是私有記憶體和公共記憶體中的變數不同步,所以計算出來的結果會和預期不一樣,也就出現了非執行緒安全問題。

      對於用volatile修飾的變數,JVM虛擬機器只是保證從主記憶體載入到執行緒工作記憶體的值是最新的,例如執行緒1和執行緒2在進行read和load的操作中,發現主記憶體中count的值都是5,那麼都會載入這個最新的值。也就是說,volatile關鍵字解決的是變數讀時的可見性問題 ,但無法保證原子性,對於多個執行緒訪問同一個例項變數還是需要加鎖同步。

例如下面方法 :
void f1() { i++; }

cpu指令如下

void f1();
Code:
0: aload_0
1: dup
2: getfield #2; //Field i:I
5: iconst_1
6: iadd
7: putfield #2; //Field i:I
10: return

可見i++執行了多部操作, 從變數i中讀取讀取i的值 -> 值+1 -> 將+1後的值寫回i中,這樣在多執行緒的時候執行情況就類似如下了

Thread1             Thread2
r1 = i;             r3 = i;               
r2 = r1 + 1;        r4 = r3 + 1;
i = r2;             i = r4;

這樣會造成的問題就是 r1, r3讀到的值都是 0, 最後兩個執行緒都將 1 寫入 i, 最後 i 等於 1, 但是卻進行了兩次自增操作

可知加了volatile和沒加volatile都無法解決非原子操作的執行緒同步問題。

正確使用 volatile 的模式

很多併發性專家事實上往往引導使用者遠離 volatile 變數,因為使用它們要比使用鎖更加容易出錯。然而,如果謹慎地遵循一些良好定義的模式,就能夠在很多場合內安全地使用 volatile 變數。要始終牢記使用 volatile 的限制 —— 只有在狀態真正獨立於程式內其他內容時才能使用 volatile —— 這條規則能夠避免將這些模式擴充套件到不安全的用例。

對於這裡我的理解是,volatile可以用於多執行緒。但是使用必須保證,同一時間只有一個執行緒對volatile修飾的物件進行修改。其他執行緒只是讀取 volatile修飾的物件值。

相關推薦

真正理解volatile關鍵字

volatile的作用 1,保證可見性 2,保證cpu指令順序執行 上面兩個特性就不過多解釋了 當volatile 修飾 int i 時,為什麼不是執行緒安全呢? 如圖: 由上,我們可以得出以下結論。 read和load階段:從主存複製變數到當前執行緒工

深入理解volatile關鍵字

最新 bsp 發現 聲明 柵欄 AD ole 情況 返回值 Java內存模型 想要理解volatile為什麽能確保可見性,就要先理解Java中的內存模型是什麽樣的。 Java內存模型規定了所有的變量都存儲在主內存中。每條線程中還有自己的工作內存,線程的工作內存中保存了被該線

深入理解Volatile關鍵字及其實現原理

volatile的用法 volatile通常被比喻成"輕量級的synchronized",也是Java併發程式設計中比較重要的一個關鍵字。和synchronized不同,volatile是一個變數修飾符,只能用來修飾變數。無法修飾方法及程式碼塊等。 volatile的用法比較簡單,只需要在

深入理解volatile關鍵字的作用(四)

前面說到的諸多概念都是為了後面的volatile做鋪墊那麼廢話不多說下面我們開始進入主題。 1、volatile的兩點語意 一但一個共享變數(類成員變數,類靜態成員變數) 被volatile修飾後那麼就具備了以下兩層語義 (1)保證不同執行緒對其的可見性,即不同執行

Java併發專題(三)深入理解volatile關鍵字

前言   上一章節簡單介紹了執行緒安全以及最基礎的保證執行緒安全的方法,建議大家手敲程式碼去體會。這一章會提到volatile關鍵字,雖然看起來很簡單,但是想徹底搞清楚需要具備JMM、CPU快取模型的知識。不要小看這個關鍵字,它在整個併發包(concurrent包)使用的非常廣泛,掌握volatile關鍵字

從計算機的角度理解volatile關鍵字

極簡計算機發展史 我們知道,計算機CPU和記憶體的互動是最頻繁的,記憶體是我們的快取記憶體區。而剛開始使用者磁碟和CPU進行互動,CPU運轉速度越來越快,磁碟遠遠跟不上CPU的讀寫速度,才設計了記憶體,但是隨著CPU的發展,記憶體的讀寫速度也遠遠跟不上CPU的讀寫速度,因此,為了解決

深入理解volatile關鍵字的作用(一)

(一)計算機記憶體模型 大家都知道在計算機執行程式的時候每條指令都是在cpu中執行的,那麼執行指令的同時勢必會有讀取和寫入的操作,那麼這樣就引申出了一個問題。那麼在程式執行時資料的儲存是在計算機中的主存中(實體記憶體)的而記憶體的讀取和寫入的速度與cpu的執行指令速度相

Java併發程式設計-正確理解volatile關鍵字的兩層語義

有序性   在Java記憶體模型中,允許編譯器和處理器對指令進行重排序,但是重排序過程不會影響到單執行緒程式的執行,卻會影響到多執行緒併發執行的正確性。   在Java裡面,可以通過volatile關鍵字來保證一定的“有序性”(具體原理在下一節講述)。另外可以通過synchronized和Lock來保

【Java併發程式設計】從CPU快取模型到JMM來理解volatile關鍵字

[toc] # 併發程式設計三大特性 ## 原子性 一個操作或者多次操作,要麼所有的操作全部都得到執行並且不會受到任何因素的干擾而中斷,**要麼所有的操作都執行,要麼都不執行**。 對於基本資料型別的訪問,讀寫都是原子性的【long和double可能例外】。 如果需要更大範圍的原子性保證,可以使用s

[C#.NET 拾遺補漏]10:理解 volatile 關鍵字

要理解 C# 中的 `volatile` 關鍵字,就要先知道編譯器背後的一個基本優化原理。比如對於下面這段程式碼: ```cs public class Example { public int x; public void DoWork() { x = 5;

對精緻碼農大佬的 [理解 volatile 關鍵字] 文章結論的思考和尋找真相

## 一:背景 ### 1. 講故事 昨天在園裡的編輯頭條看到 精緻碼農大佬 寫的一篇題為:`[C#.NET 拾遺補漏]10:理解 volatile 關鍵字` (https://www.cnblogs.com/willick/p/13889006.html) 的文章,大概就是說在 多執行緒環境下,一個

全面理解Java內存模型(JMM)及volatile關鍵字(轉)

java 關鍵字 最新版本 zed 相互 虛擬機 集成 反射機制 寄存器 原文地址: 全面理解Java內存模型(JMM)及volatile關鍵字 關聯文章: 深入理解Java類型信息(Class對象)與反射機制 深入理解Java枚舉類型(enum) 深入理解Java註

對Java單例模式 volatile關鍵字作用的理解

初始 urn class .com 重新 on() 內存空間 sta 兩個   單例模式是程序設計中經常用到的,簡單便捷的設計模式,也是很多程序猿對設計模式入門的第一節課。其中最經典的一種寫法是: class Singleton { private volatil

深入理解Java中的volatile關鍵字

語言 重新 為什麽 設置 模型 可見性 會有 普通 enter 在再有人問你Java內存模型是什麽,就把這篇文章發給他中我們曾經介紹過,Java語言為了解決並發編程中存在的原子性、可見性和有序性問題,提供了一系列和並發處理相關的關鍵字,比如synchronized、vola

關於Volatile關鍵字的一點理解

今天在看ImageLoader的原始碼的時候看到ImageLoader類裡面的單例模式的類物件宣告為<span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size:

全面理解Java記憶體模型(JMM)及volatile關鍵字

關聯文章: 本篇主要結合博主個人對Java記憶體模型的理解以及相關書籍內容的分析作為前提,對JMM進行較為全面的分析,本篇的寫作思路是先闡明Java記憶體區域劃分、硬體記憶體架構、Java多執行緒的實現原理與Java

【深入Java虛擬機器】之十一全面理解Java記憶體模型(JMM)及volatile關鍵字

轉自:https://blog.csdn.net/javazejian/article/details/72772461 關聯文章: 深入理解Java型別資訊(Class物件)與反射機制 深入理解Java列舉型別(enum) 深入理解Java註解型別(@Annotation)

volatile關鍵字理解

在這篇中我們知道引起執行緒間記憶體不可見問題,有三個原因: 1.沒有保證原子性 2.沒有保證可見性 3.沒有保證順序性 本文是本文講解的三個知識: 1.volatile關鍵字的特性是什麼? 2.如何我們要使用Java記憶體模

你真的理解了const和volatile關鍵字麼?(我看不一定)

C語言const和volatile關鍵字      這部分內容比較簡單,我這裡直接先做總結,然後通過寫三個測試程式碼,體會其中的關鍵點一、總結      1、const使得變數具有隻讀屬性(但是不一定就是不能更改)      2、const不能定義真正意義上的常量(因為有的用

深入理解Java記憶體模型JMM與volatile關鍵字

深入理解Java記憶體模型JMM與volatile關鍵字 多核併發快取架構 Java記憶體模型 Java執行緒記憶體模型跟CPU快取模型類似,是基於CPU快取模型來建立的,Java執行緒記憶體模型是標準化的,遮蔽掉了底層不同計算機的區別。 例子 編寫程式碼來分析 public class Volati