欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中保證多線程間的數(shù)據(jù)共享的方法詳解

 更新時(shí)間:2023年11月14日 11:54:23   作者:奔跑的毛球  
這篇文章詳解的發(fā)給大家介紹了Java中是如何保證多線程間的數(shù)據(jù)共享的,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

在討論這個(gè)問題之前,我們可以先瞅瞅Java的內(nèi)存模型JMM,JMM可不要和JVM混為一談。我們說的是內(nèi)存模型JMM(Java Memory Model)。

Java的內(nèi)存模型

稍微解釋一下CPU的緩存,這里CPU的緩存有三級,L1,L2和L3。

  • L1是訪問速度最快的,是線程獨(dú)享。
  • L2次之,屬于內(nèi)核獨(dú)享。
  • L3是最慢的,是多核共享。

當(dāng)CPU執(zhí)行指令需要數(shù)據(jù)的時(shí)候,會(huì)先在L1,L2,L3中依次尋找,若是找不到,則會(huì)去JVM中尋找,而JMM則在CPU和主內(nèi)存之間來保證我們需要的可見性和有序性。

這個(gè)JMM就是Java內(nèi)存模型的核心,可見性有序性都是在這里實(shí)現(xiàn)。
而主內(nèi)存就是JVM,就是我們的堆內(nèi)存。

保證可見性的方式

可見性是指,當(dāng)多個(gè)線程操作同一個(gè)數(shù)據(jù)的時(shí)候,保證一個(gè)線程的修改對其他線程是可見的,也就是說不管多個(gè)線程如何操作,如何并發(fā),他們在同一時(shí)間取到的值是相同的。

為了保證可見性,我們一般有以下幾種方案:

volatile

可以用volatile來修飾基本數(shù)據(jù)類型,可以保證每次CPU操作數(shù)據(jù)的時(shí)候,都直接操作的是主內(nèi)存的值。

文末我們會(huì)說說volatile的原理

synchronized

對于synchronized來說,是誰拿到鎖,誰執(zhí)行操作,對于拿到鎖的線程來說,前邊線程的操作是可見的。

我會(huì)另起一篇文章專門講解synchronized。

lock

lock是基于CASvolatile的修改操作,可以保證操作數(shù)據(jù)時(shí)前邊操作的可見性。

final

final修飾的是常量啊,沒法寫,只讀,當(dāng)然是全局可見的

這里有一個(gè)小點(diǎn):

我們清楚,volatile修飾基本數(shù)據(jù)類型的時(shí)候是可以保證可見性的,但是若是修飾的是引用數(shù)據(jù)類型呢?
一般沒人這么搞,甚至平時(shí)工作中volatile都很少使用,一不留神系統(tǒng)的性能會(huì)降低幾個(gè)維度。但是面試中常被問到,我們可以這樣回答:若volatile修飾的是引用數(shù)據(jù)類型,則只能保證引用數(shù)據(jù)類型的地址是可見的,里邊的值不可見。就這。

volatile的底層實(shí)現(xiàn)

稍微看看volatile的底層實(shí)現(xiàn)吧,其實(shí)

volatile的底層是匯編的lock指令,這個(gè)指令會(huì)強(qiáng)行要求將值寫入主內(nèi)存,并且忽略Store Buffer這種緩存,從而達(dá)到可見性的目的,同時(shí)利用MESI協(xié)議,讓其他緩存行失效。

我們曉得將java文件編譯為class文件的時(shí)候,會(huì)基于JIT做優(yōu)化,調(diào)整指令的順序,從而提升執(zhí)行效率,這個(gè)過程叫指令重排。
在CPU層面也會(huì)調(diào)整指令的順序來提升性能。而這個(gè)指令重排會(huì)導(dǎo)致一些問題,我們看看volatile是如何解決這個(gè)問題的。

原理

被volatile修飾的屬性,在編譯時(shí)會(huì)在先后增加內(nèi)存屏障。這里的提到的內(nèi)存屏障一般有四種

  • SS: StoreStore屏障前的讀寫操作必須全部完成,才會(huì)繼續(xù)屏障之后的操作
  • SL: StoreLoad屏障前的寫操作必須全部完成,才會(huì)繼續(xù)屏障之后的讀操作
  • LL: LoadLoad屏障前的讀操作必須全部完成,才能繼續(xù)屏障之后的讀操作
  • LS: LoadStore屏障前的讀操作必須全部完成,才能繼續(xù)屏障之后的寫操作

這里volatile的原理就如下

可以看到對于volatile的寫操作

之前添加了StoreStore內(nèi)存屏障,必須完成之前的讀寫操作才能繼續(xù)volatile的寫操作。
而后添加了StoreLoad屏障,要求其前邊的volatile寫操作完成,才能繼續(xù)之后的讀操作。

這樣就保證了在對volatile修飾的值執(zhí)行寫操作的時(shí)候,之前的讀寫操作已經(jīng)全部完成,而其后的讀操作在等待寫操作完成再去讀值。

而對于volatile的讀操作

在其后添加了一個(gè)LoadLoad屏障LoadStore屏障,這里這個(gè)LoadLoad屏障不是很理解,查閱了諸多資料也沒有眉目,若是有小伙伴知曉的,煩請不吝賜教。
LoadStore屏障則保證了volatile的讀操作全部完成之后,再繼續(xù)之后的寫操作。

這樣volatile的讀操作完成之后,才會(huì)執(zhí)行其他的寫操作。保證了讀到的值是確定的不變的。

以上就是Java中保證多線程間的數(shù)據(jù)共享的方法詳解的詳細(xì)內(nèi)容,更多關(guān)于Java多線程間的數(shù)據(jù)共享的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot項(xiàng)目編寫發(fā)送異常日志到企微工具包的操作方法

    springboot項(xiàng)目編寫發(fā)送異常日志到企微工具包的操作方法

    本文介紹了Springboot項(xiàng)目如何編寫發(fā)送異常日志到企業(yè)微信的工具包,內(nèi)容包括創(chuàng)建基礎(chǔ)Bean、配置類、pom依賴等步驟,并展示了如何通過nacos進(jìn)行配置,這為開發(fā)者提供了一種有效的日志管理方案,方便快速定位和處理項(xiàng)目中的異常問題,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • 利用Java判斷一個(gè)字符串是否包含某個(gè)字符

    利用Java判斷一個(gè)字符串是否包含某個(gè)字符

    在Java編程中,字符串操作是日常開發(fā)的常見任務(wù),涉及判斷、查找、替換等多種操作,文章介紹了如何在Java中判斷字符串是否包含某字符,提供了使用contains方法和字符數(shù)組遍歷兩種基礎(chǔ)方法,需要的朋友可以參考下
    2024-11-11
  • SpringBoot配置及使用Schedule過程解析

    SpringBoot配置及使用Schedule過程解析

    這篇文章主要介紹了SpringBoot配置及使用Schedule過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • nacos一直頻繁的打印日志get changegroupkeys問題

    nacos一直頻繁的打印日志get changegroupkeys問題

    這篇文章主要介紹了nacos一直頻繁的打印日志get changegroupkeys問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 基于JPA實(shí)體類監(jiān)聽器@EntityListeners注解的使用實(shí)例

    基于JPA實(shí)體類監(jiān)聽器@EntityListeners注解的使用實(shí)例

    這篇文章主要介紹了JPA實(shí)體類監(jiān)聽器@EntityListeners注解的使用實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • maven關(guān)于pom文件中的relativePath標(biāo)簽使用

    maven關(guān)于pom文件中的relativePath標(biāo)簽使用

    在Maven項(xiàng)目中,子工程通過<relativePath>標(biāo)簽指定父工程的pom.xml位置,以確保正確繼承父工程的配置,這個(gè)標(biāo)簽可以配置為默認(rèn)值、空值或自定義值,默認(rèn)情況下,Maven會(huì)向上一級目錄尋找父pom;若配置為空值
    2024-09-09
  • Spring利用注解整合Mybatis的方法詳解

    Spring利用注解整合Mybatis的方法詳解

    這篇文章主要為大家介紹了Spring如何利用注解整合MyBatis,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • Java編程實(shí)現(xiàn)beta分布的采樣或抽樣實(shí)例代碼

    Java編程實(shí)現(xiàn)beta分布的采樣或抽樣實(shí)例代碼

    這篇文章主要介紹了Java編程實(shí)現(xiàn)beta分布的采樣或抽樣實(shí)例,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • SpringBoot MyBatis簡單快速入門例子

    SpringBoot MyBatis簡單快速入門例子

    MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL、存儲(chǔ)過程以及高級映射。這篇文章主要介紹了SpringBoot MyBatis快速入門-簡單例子,需要的朋友可以參考下
    2021-07-07
  • SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表

    SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表

    本文主要介紹了SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論