Java并發編程中volatile實現過程詳細解析

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

  首先并發編程有三大特性:?可見性,有序性,原子性。volatile關鍵字實現了前面兩個特性。那么它是如何實現這兩個特性的呢?

  首先是可見性。可見性主要是讓緩存,直接寫穿透到主存中。然后另外的cpu?通過底層的硬件層面的嗅探,可以發現自己cpu本地的緩存已經失效。然后到主存中直接讀取。現在讓我們來看看,cpu里面的緩存具體和主存如何交互。

  說道這里首先需要了解,計算機內部存儲器結構。每個核中都有自己的通用寄存器,比如eax,ebx,edx,esi,esp.訪問這些寄存器里面的內容,只要一個機器周期,就夠了,通常小于1ns..然后是L1,L2的本地core的緩存。?通常在10個機器周期左右。大約10ns. L3級緩存是多core共享的。

? ? ? 以我們常見的X86芯片為例,Cache的結構下圖所示:整個Cache被分為S個組,每個組是又由E行個最小的存儲單元——Cache Line所組成,而一個Cache Line中有B(B=64)個字節用來存儲數據,即每個Cache Line能存儲64個字節的數據,每個Cache Line又額外包含一個有效位(valid bit)、t個標記位(tag bit),其中valid bit用來表示該緩存行是否有效;tag bit用來協助尋址,唯一標識存儲在CacheLine中的塊;而Cache Line里的64個字節其實是對應內存地址中的數據拷貝。根據Cache的結構題,我們可以推算出每一級Cache的大小為B×E×S。 ??

1級大概是32k?或者32K X2? ,2級大概是 256K或者256KX2 ,L3一般是3M左右。當多線程并發訪問一段代碼的時候,讀取變量到本地的core進行計算,然后把數據寫入到緩存中,假如沒有volatile關鍵字的話,緩存采用的是write back?策略,直接寫到緩存,看如下代碼,雖然啟用了10個線程進行計數,但是打印出來的count值是0.即使sleep(100),100ms,等所有線程都起來了,也是得到的結果都是不定的,因為無法確定緩存什么時候,換出寫到主存中。

1 public class VolatileTest {
2
3???? private int count ;
4???? public void increase() {
5???????? count++;
6???? }
7???? public void? getCount(){
8???????? System.out.println(count);
9???? }
10???? public static void main(String[] args) throws InterruptedException{
11???????? VolatileTest test =? new VolatileTest();
12???????? for(int i=0;i<10;i++){
13???????????? new Thread(){
14???????????????? @Override
15???????????????? public void run() {
16???????????????????? for(int j=0;j<1000;j++)
17???????????????????????? test.increase();
18???????????????? }
19???????????? }.start();
20???????? }
21???????? Thread.sleep(100);
22???????? test.getCount();
23???? }
24 }

???? volatile?作用1?就是一個線程改變了共享變量的值,其它線程馬上能看見,就是可見性。比如下面的這段代碼。

?1?import?java.util.concurrent.CountDownLatch;?2??3?public?class?VolatileTest2?{?4??5?????private?static?volatile?boolean?status=false?;?6??7?????private?static?CountDownLatch?start??=?new?CountDownLatch(1);?8??9?????public?void?setStatusTrue(){10?????????status?=true;11?????}12?????public?void??getStatus(){13?????????System.out.println(status);14?????}15?????public?static?void?main(String[]?args)?throws?InterruptedException{16?????????VolatileTest2?test?=??new?VolatileTest2();17?????????new?Thread(new?Task2(start,test)).start();18?????????for(int?i=0;i<10;i++){19?????????????new?Thread(new?Task1(start,test)).start();20?????????}21?????}22?}23?24?class?Task1?implements?Runnable{25?????private?CountDownLatch?latch;26?????private?VolatileTest2?test?;27?????public?Task1(CountDownLatch?start,VolatileTest2?test){28?????????this.latch?=?start;29?????????this.test?=?test;30?????}31?????@Override32?????public?void?run()?{33?????????try{34????????????latch.await();35?????????}catch?(Exception?e){36?????????}37?????????????test.getStatus();38?????}39?}40?41?/**42??*?這個線程吧狀態設置成true,然后同步計數器馬上變成0.之后,就其它線程馬上就能看到status狀態為true43??*/44?class?Task2?implements?Runnable{45?????private?CountDownLatch?latch;46?????private?VolatileTest2?test?;47?????public?Task2(CountDownLatch?start,VolatileTest2?test){48?????????this.latch?=?start;49?????????this.test?=?test;50?????}51?????@Override52?????public?void?run()?{53?????????test.setStatusTrue();54?????????latch.countDown();55?????????System.out.println("countDown===");56?????}57?}

? ? ?? 具體的原理,這里涉及到緩存一致性原理,MESI 協議

? ? ?? 失效(Invalid)緩存段,要么已經不在緩存中,要么它的內容已經過時。為了達到緩存的目的,這種狀態的段將會被忽略。一旦緩存段被標記為失效,那效果就等同于它從來沒被加載到緩存中。

?????? 共享(Shared)緩存段,它是和主內存內容保持一致的一份拷貝,在這種狀態下的緩存段只能被讀取,不能被寫入。多組緩存可以同時擁有針對同一內存地址的共享緩存段,這就是名稱的由來。

?????? 獨占(Exclusive)緩存段,和S狀態一樣,也是和主內存內容保持一致的一份拷貝。區別在于,如果一個處理器持有了某個E狀態的緩存段,那其他處理器就不能同時持有它,所以叫“獨占”。這意味著,如果其他處理器原本也持有同一緩存段,那么它會馬上變成“失效”狀態。

?????? 已修改(Modified)緩存段,屬于臟段,它們已經被所屬的處理器修改了。如果一個段處于已修改狀態,那么它在其他處理器緩存中的拷貝馬上會變成失效狀態,這個規律和E狀態一樣。此外,已修改緩存段如果被丟棄或標記為失效,那么先要把它的內容回寫到內存中——這和回寫模式下常規的臟段處理方式一樣。

?????? 在寫入時鎖定緩存,稱為Exclusive狀態,然后同時寫入緩存和主存,當讀取數據的時候,強行,從主存中讀取,并且申請緩存行填充。

2?有序性,這個又如何保證呢?

?????? 《深入理解Java虛擬機》中有這句話“”“觀察加入volatile關鍵字和沒有加入volatile關鍵字時所生成的匯編代碼發現,加入volatile關鍵字時,會多出一個lock前綴指令”“”,lock前綴指令實際上相當于一個內存屏障(也成內存柵欄)它確保指令重排序時不會把其后面的指令排到內存屏障之前的位置,也不會把前面的指令排到內存屏障的后面;即在執行到內存屏障這句指令時,在它前面的操作已經全部完成;至于什么是內存屏障,不做深入了解。只需要知道是CPU Out-of-order execution 和 compiler reordering optimizations。用于對內存操作的順序限制。

Memory access instructions, such as loads and stores, typically take longer to execute than other instructions. Therefore, compilers use registers to hold frequently used values and processors use high speed caches to hold the most frequently used memory locations. Another common optimization is for compilers and processors to rearrange the order that instructions are executed so that the processor does not have to wait for memory accesses to complete. This can result in memory being accessed in a different order than specified in the source code. While this typically will not cause a problem in a single thread of execution, it can cause a problem if the location can also be accessed from another processor or device.

轉載于:https://my.oschina.net/u/3980693/blog/2967178

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

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

相關文章

《ASP.NET Core 6框架揭秘》實例演示[32]:錯誤頁面的N種呈現方式

由于ASP.NET是一個同時處理多個請求的Web應用框架&#xff0c;所以在處理某個請求過程中出現異常并不會導致整個應用的中止。出于安全方面的考量&#xff0c;為了避免敏感信息外泄&#xff0c;客戶端在默認情況下并不會得到詳細的出錯信息&#xff0c;這無疑會在開發過程中增加…

SpringMVC接受JSON參數詳解及常見錯誤總結我改

SpringMVC接受JSON參數詳解及常見錯誤總結 最近一段時間不想使用Session了&#xff0c;想感受一下Token這樣比較安全&#xff0c;穩健的方式&#xff0c;順便寫一個統一的接口給瀏覽器還有APP。所以把一個練手項目的前臺全部改成Ajax了&#xff0c;跳轉再使用SpringMVC控制轉發…

軟件定義存儲的定制化怎么走?

引言 當前&#xff0c;軟件定義存儲成為業內超高速增長的典型。有研究人員稱&#xff0c;從2014年到2019年&#xff0c;軟件定義存儲市場將從14億美元增長到62億美元以上&#xff0c;年復合增長率將達35%。軟件定義存儲所帶來的優勢顯而易見&#xff0c;但是對于企業來說&#…

Golang并發模型:合理退出并發協程

goroutine作為Golang并發的核心&#xff0c;我們不僅要關注它們的創建和管理&#xff0c;當然還要關注如何合理的退出這些協程&#xff0c;不&#xff08;合理&#xff09;退出不然可能會造成阻塞、panic、程序行為異常、數據結果不正確等問題。這篇文章介紹&#xff0c;如何合…

劍網服務器維護,12月31日服務器例行維護公告

隱元秘鑒新增以下江湖行里使用趣味道具的成就&#xff1a;壓酒喚客嘗&#xff1a;使用壓酒三十次欲解紅燭意&#xff1a;使用燭影三十次閑情吹笛子&#xff1a;使用吹斷三十次引弦中落雀&#xff1a;使用千鳥三十次黃云動風色&#xff1a;使用風色三十次卷抒平生意&#xff1a;…

一款 Windows 軟件快捷助手

WPF 開發的 Windows 軟件快捷助手Windows 軟件快捷助手作者&#xff1a;WPFDevelopersOrg - 驚鏵原文鏈接&#xff1a;https://github.com/WPFDevelopersOrg/SoftwareHelper框架使用.NET40&#xff1b;Visual Studio 2019;項目使用 MIT 開源許可協議&#xff1b;項目使用 MVV…

關于8位AD_DA轉換芯片的采樣率問題

關于使用Keil計算程序執行時間 打開Keil程序&#xff0c;進入“啟動/停止調試”界面。在需要暫停的地方設置斷點&#xff08;在該句程序前雙擊&#xff09;。在程序上方有一行工具欄&#xff1a;此工具欄分別代表復位、運行、停止、步進、步越、步出、運行到光標處等。 點擊運…

CYQ.Data 數據框架 V4.0 開源版本發布(源碼提供下載,秋色園V2.5版本標配框架)

說明的說明&#xff1a; 博客園團隊兩次移此文出首頁&#xff0c;說 這篇文章不屬于知識分享型文章&#xff0c;并且有廣告嫌疑。 本文的確屬于分享型文章&#xff0c;而且分享的知識點比其它文章都多很多&#xff0c;看看網友回復“謝謝分享”就知道是分享型文章了。 所謂廣告…

oracle 分組后取每組第一條數據

數據格式 分組取第一條的效果 sql SELECT * FROM (SELECT ROW_NUMBER() OVER(PARTITION BY x ORDER BY y DESC) rn, test1.* FROM test1) WHERE rn 1 ;

永大服務器進去顯示字母,永大電梯服務器使用說明

永大電梯服務器使用說明2021-05-25一&#xff0e; 目的&#xff1a;用于工務交車前對MPU和XDR板進行調試。二&#xff0e; 對應作業&#xff1a;1-1對MPU電梯調試接線連接&#xff1a;1).對MPUGB2(A2)版電梯調試時(以及A2前版本)&#xff0c;接線情況如下&#xff1a;連接順序連…

樹莓派Zero 2 W(ubuntu-22.04)通過.NET6和libusb操作USB讀寫

有這個想法的初衷喜歡電子和DIY硬件的朋友對稚暉君應該都不陌生&#xff0c;他定期都會分享一些自己做的好玩的硬件&#xff0c;他之前做了一個ElectronBot桌面機器人我就很感興趣&#xff0c;所以就自己也做了一個。起初我只是自己開發了一個叫電子腦殼的上位機軟件&#xff0…

bzoj4589

fwt 原理并不知道 nim游戲石子異或和0后手贏 那么也就是求a[1]^a[2]^...^a[n]0的方案數 這個和bzoj3992一樣可以dp dp[i][j]表示前i個數異或和為j的方案數 dp[0][0] 1 dp[i][j] dp[i - 1][k] * a[p] p ^ k j a[p] 0 / 1 表示有沒有p這個數 這個東西也不能矩陣快速冪 但是我…

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 85

UnicodeDecodeError: ascii codec cant decode byte 0xe5 in position 85;import sys reload(sys) sys.setdefaultencoding(utf8)

JS設計模式五:職責鏈模式

職責鏈模式簡述 職責連是由多個不同的對象組成的&#xff0c;有發送者跟接收者&#xff0c;分別負責信息的發送跟接收&#xff0c;其中&#xff0c;鏈中第一個對象是 職責連是由多個不同的對象組成的&#xff0c;發送者是發送請求的對象&#xff0c;接收者接收請求并且對其進行…

web框架之Django(一)

Python的WEB框架有Django、Tornado、Flask 等多種&#xff0c;Django相較與其他WEB框架其優勢為&#xff1a;大而全&#xff0c;框架本身集成了ORM、模型綁定、模板引擎、緩存、Session等諸多功能。 基本配置 一、創建django程序 終端命令&#xff1a;django-admin startprojec…

寫一個易于維護使用方便性能可靠的Hybrid框架(一)—— 思路構建

寫一個易于維護使用方便性能可靠的Hybrid框架&#xff08;二&#xff09;—— 插件化 寫一個易于維護使用方便性能可靠的Hybrid框架&#xff08;三&#xff09;—— 配置插件 前言 本來上一篇博文寫完&#xff0c;我就告訴自己&#xff0c;這是最后一篇&#xff0c;之后不再總結…

程序員制作出價值5億外賣神器卻不能取消訂單,你知道嗎?

小編今日給大家帶來RACDisopsable&#xff0c;大家可能有部分人對這個會感覺到很陌生&#xff0c;那么我就用一句話來表達就是他可以幫我們取消訂閱。那么又會有人會對這個產生疑問了&#xff0c;我們什么時候需要用到這個取消訂閱了打個實際的例子來說吧&#xff0c;今天我在餓…

Computer

鏈接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid2196https://blog.csdn.net/shuangde800/article/details/9732825#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<cmath&…

智慧“昆明”在路上 未來充滿精彩

智慧城市是運用物聯網、云計算、大數據、移動互聯網、空間地理信息集成等新一代信息技術&#xff0c;促進城市規劃、建設、管理和服務智慧化的新理念和新模式。近年來&#xff0c;昆明市全面加快智慧城市建設&#xff0c;力爭通過三年的努力&#xff0c;打造區域信息輻射中心的…

《精讀 Mastering ABP Framework》教程發布

精讀《Mastering ABP Framework》學習總結&#xff0c;掌握軟件開發最佳實踐&#xff0c;構建可維護 .NET 解決方案。從 ABP Framework 框架中學習如何構建現代 WEB 應用程序。掌握 ABP Framework 框架ABP Framework 是一個完整的基礎架構&#xff0c;遵循軟件開發最佳實踐&…