Java之volatile如何保證可見性和指令重排序

1 我們先了解CPU緩存

CPU緩存為了解決CPU運算速度與內存讀寫速度不匹配的問題,因為CPU運算速度要比內存讀寫速度快得多

  • 一次主內存的訪問通常在幾十到幾百個時鐘周期
  • 一次L1高速緩存的讀寫只需要1~2個時鐘周期
  • 一次L2高速緩存的讀寫也只需要數十個時鐘周期

CPU大多數情況下讀寫都不會直接訪問內存,取而代之的是CPU緩存,CPU緩存是位于CPU與內存之間的臨時存儲器(簡單理解為寄存器)它容量比內存小得多但是交換速度卻比內存快得多。而緩存中的數據是內存中的一小部分數據,但這一小部分是短時間內CPU即將訪問的,當CPU調用大量數據時,就可先從緩存中讀取,從而加快讀取速度

CPU緩存可分為:一級緩存(是與CPU結合最為緊密的CPU緩存二級緩存三級緩存,每一級緩存中所存儲的數據全部都是下一級緩存中的一部分

CPU要讀取數據時,首先從一級緩存中查找,如果沒有再從二級緩存中查找,如果還是沒有再從三級緩存中或內存中查找。一般來說每級緩存的命中率大概都有80%左右,只剩下20%的總數據量才需要從二級緩存、三級緩存或內存中讀取。

CPU執行計算的過程如下:

  • 程序以及數據被加載到主內存
  • 指令和數據被加載到CPU緩存
  • CPU執行指令,把結果寫到高速緩存
  • 高速緩存中的數據寫回主內存

?

?

?

?

?

?

?

2?總線鎖

每個CPU都有一級緩存,但是,我們卻無法保證每個CPU的一級緩存數據都是一樣的,如何保證各個CPU緩存中的數據是一致的。就是CPU的緩存一致性問題

1)總線鎖

一種處理一致性問題的辦法是使用Bus Locking(總線鎖)。當一個CPU對其緩存中的數據進行操作的時候,往總線中發送一個Lock信號。 這個時候,所有CPU收到這個信號之后就不操作自己緩存中的對應數據了,也就是把數據直接寫入主內存,當操作結束,釋放鎖以后,所有的CPU就去內存中獲取最新數據更新

?

?

?

?

?

?

?

3?volatile如何保證可見性

我們把有volatile修飾的變量編譯成部分匯編,這里有個lock指令

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

如果是寫操作,cpu會發出一個lock指令,CUP會把數據直接寫到到主內存

如果是讀操作,cpu會發出一個unlock指令,?所有的CPU就去內存中獲取最新數據更新

?

?

?

?

?

?

?

4 volatile如何保證指令重排序

現代的操作系統都是多處理器.而每一個處理器都有自己的緩存,并且這些緩存并不是實時都與內存發生信息交換.這樣就可能出現一個cpu上的緩存數據與另一個cpu上的緩存數據不一致的問題.而這樣在多線程開發中,就有可能導致出現一些異常行為.
而操作系統底層為了這些問題,提供了一些內存屏障用以解決這樣的問題.目前有4種屏障.

  • LoadLoad屏障:對于這樣的語句Load1; LoadLoad; Load2,在Load2及后續讀取操作要讀取的數據被訪問前,保證Load1要讀取的數據被讀取完畢。
  • StoreStore屏障:對于這樣的語句Store1; StoreStore; Store2,在Store2及后續寫入操作執行前,保證Store1的寫入操作對其它處理器可見。
  • LoadStore屏障:對于這樣的語句Load1; LoadStore; Store2,在Store2及后續寫入操作被刷出前,保證Load1要讀取的數據被讀取完畢。
  • StoreLoad屏障:對于這樣的語句Store1; StoreLoad; Load2,在Load2及后續所有讀取操作執行前,保證Store1的寫入對所有處理器可見。

在每個volatile寫操作前插入StoreStore屏障,在寫操作后插入StoreLoad屏障;
在每個volatile讀操作前插入LoadLoad屏障,在讀操作后插入LoadStore屏障;
?

由于內存屏障的作用,避免了volatile變量和其它指令重排序?

?

?

?

?

?

參考鏈接:

https://crowhawk.github.io/2018/02/10/volatile/

https://www.jianshu.com/p/ef8de88b1343

https://my.oschina.net/LucasZhu/blog/1537330

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/287773.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/287773.shtml
英文地址,請注明出處:http://en.pswp.cn/news/287773.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

bigpipe提升網站響應速度

2019獨角獸企業重金招聘Python工程師標準>>> 主要思想就是通過異步 發起一次請求,后端不關閉輸出流,多個線程處理各自任務,然后分別發送到客戶端。 https://github.com/4rnold/Demo-Project/tree/master/bigpipe-demohttps://gith…

mysql 添加用戶_mysql創建用戶與授權

一、創建用戶CREATE USER usernamehost IDENTIFIED BY password;說明username:你將創建的用戶名host:指定該用戶在哪個主機上可以登陸,如果是本地用戶可用localhost,如果想讓該用戶可以從任意遠程主機登陸,可以使用通配…

《零基礎看得懂的C語言入門教程 》——(十一)C語言自定義函數真的很簡單

一、學習目標 了解C語言的自定義函數的使用方法了解C語言自定義函數的傳參了解C語言自定義函數的返回值 目錄 C語言真的很難嗎?那是你沒看這張圖,化整為零輕松學習C語言。 第一篇:(一)脫離學習誤區 第二篇&#xf…

T-SQL編程基礎之二:條件選擇、循環編程

1. 條件判斷以及GOTO語句 條件判斷是計算機語言的重要功能,在T-SQL中,條件判斷的語句是: if 條件 … else … 或者是: if 條件 … 注意寫法和C類似,但條件描述不使用()也可以。如果是在一個條件里執行多條語句,則要構造復合語句,復合語句是在BEGIN…EDN中構造…

**【ci框架】精通CodeIgniter框架

http://blog.csdn.net/yanhui_wei/article/details/25803945 一、大綱 [php] view plaincopy1、codeigniter框架的授課內容安排 2、codeigniter框架的簡介 |-----關于框架的概念 |-----使用CI框架的好處 |-----為什么選擇CI框架 3、codeigniter框架…

AspNetCore開源中間件-VueRouterHistory

前言用過VueRouter路由組件的應該都知道,VueRouter有hash和history兩種模式。hash模式會在url中插入#,history模式下url則看上去更加簡潔美觀。如果想要支持history模式則必須要后端服務進行配合。常用后端服務器配置方式請參考 后端配置例子后端配置例子…

T-SQL編程基礎之三:游標(Cursor)編程

SQL是一種面向集合操作的語言,大多情況下,一個SQL語句將會操作數據庫表里的很多數據,基本上,一個數據庫的程序員腦子里應該想的是如何整體操作一個表或者是幾個表。 但也有一些情況下,試圖整表操作是不現實的,需要一行一行處理數據,這種情況下,SQL語言提供了所謂游標的…

《假如編程是魔法之零基礎看得懂的Python入門教程 》——(一)既然你選擇了這系列教程那么我就要讓你聽得懂

一、前言 幾個月前編寫了一份python語言入門的博文,近期重新審閱了一遍發現編寫的質量太過隨意,可能對于一部分人并不是非常友好,故此重新編寫Python語言的零基礎教程。 本篇教程將會盡量把一些專業術語給讀者講解清楚,并且讓讀…

centos 7下安裝mysql_Centos7下安裝MySQL5.7(數據庫的最全安裝方法)

Centos7下使用yum安裝mysql數據庫首先Centox7已經不支持mysql,因為收費了你懂得,所以內部集成了mariadb,而安裝mysql的話會和mariadb的文件沖突,所以需要先卸載掉mariadb。由于確定使用mysql,那只有卸載mariadb了。一、…

環形隊列

在網上看到一篇比較好的介紹隊列的文章,地址為:http://www.cnblogs.com/kubixuesheng/p/4104802.html 特此感謝原創作者,以下均為摘抄。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1、…

HTTP1.0、HTTP1.1 、SPDY、HTTP2.0之演變過程和優化

一、協議的演變過程和時間 HTTP1.0(1996年) -> HTTP1.1(1999年) -> SPDY(2012年google提出了SPDY的方案) -> HTTP2.0(2013年8月進行首次合作共事性測試) 二、影響一個HTTP網絡請求的因素 主要有兩個:帶寬和延遲 1)帶寬:網絡基礎建設已經使得帶寬得到極大的提升…

OK335xS GPMC nand device register hacking

/********************************************************************************** OK335xS GPMC nand device register hacking* 說明:* 由于最近遇到No NAND device found這個內核錯誤,在網絡上也沒找到很好的* 解決辦法&am…

Blazor University (19)使用 RenderFragments 模板化組件 —— 數據傳遞

原文鏈接:https://blazor-university.com/templating-components-with-renderfragements/passing-data-to-a-renderfragement/將數據傳遞給 RenderFragment源代碼[1]到目前為止,我們使用了僅包含子標記的 RenderFragments,然后在渲染組件時按…

一頭扎進Node(三) - File System

file.open:異步模式打開文件 fs.open(path, flags[, mode], callback) 案例代碼如下: var fs require(fs);/*** 參數說明:* 1.path:要打開的文件的文件路徑* 2.flags:打開文件的方式 讀/寫* r:只讀方式打開文件…

《零基礎看得懂的C語言入門教程 》——(十二)原來結構體是這么回事

一、學習目標 了解C語言的結構體的使用方法了解C語言結構體的結構的賦值了解多種C語言結構體變量的賦值方法和取值方法 目錄 C語言真的很難嗎?那是你沒看這張圖,化整為零輕松學習C語言。 第一篇:(一)脫離學習誤區 第…

【學生選課系統經典】C#與SQLSERVER連接:Windows應用工程案例

實驗任務描述 1 用C#訪問SQLSERVER數據庫(兩種安全模式); 2 用C#完成數據庫指定表上的數據顯示; 3 用C#完成數據庫指定表上的數據插入、刪除和更新; 4 用C#完成數據庫用戶驗證。 注意,由于C#語言的強大功能,下面的代碼適用于SQLSERVER2000、也適合于SQLSERVER2005。區別僅…

Java精選筆記_JDBC

JDBC概述 什么是JDBC JDBC全稱是Java數據庫連接(Java Database Connectivity),應用程序可通過這套API連接到關系數據庫,并使用SQL語句來完成對數據庫中數據的查詢、更新和刪除等操作。是一套用于執行SQL語句的Java API。Java的數據…

mysql關系數據庫引擎_MySQL數據庫引擎詳解

作為Java程序員,MySQL數據庫大家平時應該都沒少使用吧,對MySQL數據庫的引擎應該也有所了解,這篇文章就讓我詳細的說說MySQL數據庫的Innodb和MyIASM兩種引擎以及其索引結構。也來鞏固一下自己對這塊知識的掌握。Innodb引擎Innodb引擎提供了對數…

Java之synchronized的JVM底層實現原理精簡理解

1 synchronized的JVM底層原理實現的精簡理解 Java 虛擬機中的synchronized基于進入和退出Monitor對象(也稱為管程或監視器鎖)實現, 無論是顯式同步(synchronized作用在同步代碼塊,有明確的 monitorenter 和 monitorexit 指令) 還是…

三分鐘掌握Actor和CSP模型

點擊上方藍字進行關注前文傳送門:《三分鐘掌握共享內存模型和 Actor模型》, 一直想比較Actor模型與golang的CSP模型,經過一段時間的實戰記錄了本文。Actor vs CSP模型? 傳統多線程的的共享內存(ShareMemory)模型使用l…