偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

解決Java并發(fā)可見性問(wèn)題,Volatile閃亮登場(chǎng)

開發(fā) 前端
volatile主要解決的是一個(gè)線程修改變量值之后,其他線程立馬可以讀到最新的值,是解決這個(gè)問(wèn)題的,也就是可見性!

場(chǎng)景引入,問(wèn)題初現(xiàn)

很多同學(xué)出去面試,都會(huì)被問(wèn)到一個(gè)常見的問(wèn)題:說(shuō)說(shuō)你對(duì)volatile的理解?

不少初出茅廬的同學(xué)可能會(huì)有點(diǎn)措手不及,因?yàn)榭赡芫褪侵皼](méi)關(guān)注過(guò)這個(gè)。但是網(wǎng)上百度一下呢,不少文章寫的很好,但是理論扎的太深,文字太多,圖太少,讓人有點(diǎn)難以理解。

基于上述痛點(diǎn),這篇文章嘗試站在年輕同學(xué)的角度,用最簡(jiǎn)單的大白話,加上多張圖給大家說(shuō)一下,volatile到底是什么?

當(dāng)然本文不會(huì)把理論扎的太深,因?yàn)橐幌伦釉盍宋淖痔?,很多同學(xué)還是會(huì)不好理解。

本文僅僅是定位在用大白話的語(yǔ)言將volatile這個(gè)東西解釋清楚,而涉及到特別底層的一些原理和技術(shù)問(wèn)題,以后有機(jī)會(huì)開文再寫。

首先,給大家上一張圖,咱們來(lái)一起看看:

完美解決java并發(fā)可見性問(wèn)題,volatile閃亮登場(chǎng)

如上圖,這張圖說(shuō)的是java內(nèi)存模型中,每個(gè)線程有自己的工作內(nèi)存,同時(shí)還有一個(gè)共享的主內(nèi)存。

舉個(gè)例子,比如說(shuō)有兩個(gè)線程,他們的代碼里都需要讀取data這個(gè)變量的值,那么他們都會(huì)從主內(nèi)存里加載data變量的值到自己的工作內(nèi)存,然后才可以使用那個(gè)值。

好了,現(xiàn)在大家從圖里看到,每個(gè)線程都把data這個(gè)變量的副本加載到了自己的工作內(nèi)存里了,所以每個(gè)線程都可以讀到data = 0這個(gè)值。

這樣,在線程代碼運(yùn)行的過(guò)程中,對(duì)data的值都可以直接從工作內(nèi)存里加載了,不需要再?gòu)闹鲀?nèi)存里加載了。

那問(wèn)題來(lái)了,為啥一定要讓每個(gè)線程用一個(gè)工作內(nèi)存來(lái)存放變量的副本以供讀取呢?我直接讓線程每次都從主內(nèi)存加載變量的值不行嗎?

很簡(jiǎn)單!因?yàn)榫€程運(yùn)行的代碼對(duì)應(yīng)的是一些指令,是由CPU執(zhí)行的!但是CPU每次執(zhí)行指令運(yùn)算的時(shí)候,也就是執(zhí)行我們寫的那一大坨代碼的時(shí)候,要是每次需要一個(gè)變量的值,都從主內(nèi)存加載,性能會(huì)比較差!

所以說(shuō)后來(lái)想了一個(gè)辦法,就是線程有工作內(nèi)存的概念,類似于一個(gè)高速的本地緩存。

這樣一來(lái),線程的代碼在執(zhí)行過(guò)程中,就可以直接從自己本地緩存里加載變量副本,不需要從主內(nèi)存加載變量值,性能可以提升很多!

但是大家思考一下,這樣會(huì)有什么問(wèn)題?

我們來(lái)設(shè)想一下,假如說(shuō)線程1修改了data變量的值為1,然后將這個(gè)修改寫入自己的本地工作內(nèi)存。那么此時(shí),線程1的工作內(nèi)存里的data值為1。

然而,主內(nèi)存里的data值還是為0!線程2的工作內(nèi)存里的data值還是0?。?!

完美解決java并發(fā)可見性問(wèn)題,volatile閃亮登場(chǎng)

這可尷尬了,那接下來(lái),在線程1的代碼運(yùn)行過(guò)程中,他可以直接讀到data最新的值是1,但是線程2的代碼運(yùn)行過(guò)程中讀到的data的值還是0!

這就導(dǎo)致,線程1和線程2其實(shí)都是在操作一個(gè)變量data,但是線程1修改了data變量的值之后,線程2是看不到的,一直都是看到自己本地工作內(nèi)存中的一個(gè)舊的副本的值!

這就是所謂的java并發(fā)編程中的可見性問(wèn)題:

多個(gè)線程并發(fā)讀寫一個(gè)共享變量的時(shí)候,有可能某個(gè)線程修改了變量的值,但是其他線程看不到!也就是對(duì)其他線程不可見!

volatile的作用及背后的原理

那如果要解決這個(gè)問(wèn)題怎么辦呢?這時(shí)就輪到volatile閃亮登場(chǎng)了!你只要給data這個(gè)變量在定義的時(shí)候加一個(gè)volatile,就直接可以完美的解決這個(gè)可見性的問(wèn)題。

比如下面的這樣的代碼,在加了volatile之后,會(huì)有啥作用呢?

完美解決java并發(fā)可見性問(wèn)題,volatile閃亮登場(chǎng)

完整的作用就不給大家解釋了,因?yàn)槲覀兌ㄎ痪褪谴蟀自?,要是把底層涉及的各種內(nèi)存屏障、指令重排等概念在這里帶出來(lái),不少同學(xué)又要蒙圈了!

我們這里,就說(shuō)說(shuō)他最關(guān)鍵的幾個(gè)作用是啥?

第一,一旦data變量定義的時(shí)候前面加了volatile來(lái)修飾的話,那么線程1只要修改data變量的值,就會(huì)在修改完自己本地工作內(nèi)存的data變量值之后,強(qiáng)制將這個(gè)data變量最新的值刷回主內(nèi)存,必須讓主內(nèi)存里的data變量值立馬變成最新的值!

整個(gè)過(guò)程,如下圖所示:

完美解決java并發(fā)可見性問(wèn)題,volatile閃亮登場(chǎng)

第二,如果此時(shí)別的線程的工作內(nèi)存中有這個(gè)data變量的本地緩存,也就是一個(gè)變量副本的話,那么會(huì)強(qiáng)制讓其他線程的工作內(nèi)存中的data變量緩存直接失效過(guò)期,不允許再次讀取和使用了!

整個(gè)過(guò)程,如下圖所示:

完美解決java并發(fā)可見性問(wèn)題,volatile閃亮登場(chǎng)

第三,如果線程2在代碼運(yùn)行過(guò)程中再次需要讀取data變量的值,此時(shí)嘗試從本地工作內(nèi)存中讀取,就會(huì)發(fā)現(xiàn)這個(gè)data = 0已經(jīng)過(guò)期了!

此時(shí),他就必須重新從主內(nèi)存中加載data變量最新的值!那么不就可以讀取到data = 1這個(gè)最新的值了!整個(gè)過(guò)程,參見下圖:

完美解決java并發(fā)可見性問(wèn)題,volatile閃亮登場(chǎng)

bingo!好了,volatile完美解決了java并發(fā)中可見性的問(wèn)題!

對(duì)一個(gè)變量加了volatile關(guān)鍵字修飾之后,只要一個(gè)線程修改了這個(gè)變量的值,立馬強(qiáng)制刷回主內(nèi)存。

接著強(qiáng)制過(guò)期其他線程的本地工作內(nèi)存中的緩存,最后其他線程讀取變量值的時(shí)候,強(qiáng)制重新從主內(nèi)存來(lái)加載最新的值!

這樣就保證,任何一個(gè)線程修改了變量值,其他線程立馬就可以看見了!這就是所謂的volatile保證了可見性的工作原理!

總結(jié) & 提醒

最后給大家提一嘴,volatile主要作用是保證可見性以及有序性。

有序性涉及到較為復(fù)雜的指令重排、內(nèi)存屏障等概念,本文沒(méi)提及,但是volatile是不能保證原子性的!

也就是說(shuō),volatile主要解決的是一個(gè)線程修改變量值之后,其他線程立馬可以讀到最新的值,是解決這個(gè)問(wèn)題的,也就是可見性!

但是如果是多個(gè)線程同時(shí)修改一個(gè)變量的值,那還是可能出現(xiàn)多線程并發(fā)的安全問(wèn)題,導(dǎo)致數(shù)據(jù)值修改錯(cuò)亂,volatile是不負(fù)責(zé)解決這個(gè)問(wèn)題的,也就是不負(fù)責(zé)解決原子性問(wèn)題!?

責(zé)任編輯:武曉燕 來(lái)源: 今日頭條
相關(guān)推薦

2024-02-27 17:46:25

并發(fā)程序CPU

2019-07-29 08:22:48

SIEM安全信息和事件管理系統(tǒng)應(yīng)用安全

2020-02-28 14:48:51

結(jié)構(gòu)系統(tǒng)程序

2018-08-07 16:01:32

synchronizevolatilefinal

2019-08-19 15:36:55

SynchronizeVolatile性能

2021-07-06 14:47:30

Go 開發(fā)技術(shù)

2014-02-26 14:57:26

云計(jì)算

2011-01-18 14:13:37

Firefox4.0火狐瀏覽器

2010-06-30 09:26:43

Firefox 4.0

2016-11-11 00:39:59

Java可見性機(jī)制

2012-04-09 16:56:41

戴爾

2016-09-19 21:53:30

Java并發(fā)編程解析volatile

2012-08-15 15:45:46

Surface平板微軟

2016-03-27 16:52:38

北信源/Linkdoo

2022-12-04 09:19:25

JAVA并發(fā)有序性

2009-11-04 10:15:27

Ubuntu袁萌Ubuntu 9.10

2016-07-04 08:19:13

混合IT網(wǎng)絡(luò)問(wèn)題SaaS

2016-07-29 17:08:30

修復(fù)網(wǎng)絡(luò)問(wèn)題

2022-05-05 07:38:32

volatilJava并發(fā)

2014-05-06 15:57:04

傲游Android極速
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)