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

關(guān)于Java中的可見性和有序性問題

 更新時(shí)間:2023年08月07日 08:54:48   作者:吃飯只吃豬腳飯  
這篇文章主要介紹了關(guān)于Java中的可見性和有序性問題,Java在誕生之初就支持多線程,自然也有針對(duì)這三者的技術(shù)方案,今天就學(xué)習(xí)一下Java如何解決其中的可見性和有序性導(dǎo)致的問題,需要的朋友可以參考下

Java 如何解決可見性和有序性問題

并發(fā)場(chǎng)景中,因可見性、原子性、有序性導(dǎo)致問題常常導(dǎo)致bug,Java在誕生之初就支持多線程,自然也有針對(duì)這三者的技術(shù)方案

今天就學(xué)習(xí)一下Java如何解決其中的可見性和有序性導(dǎo)致的問題,就引來了今天的主角兒——Java內(nèi)存模型

什么是Java內(nèi)存模型

? 導(dǎo)致可見性的原因是緩存,導(dǎo)致有序性的原因是編譯優(yōu)化

解決可見性、有序性最直接的方法就是禁用緩存和編譯優(yōu)化,但這樣會(huì)導(dǎo)致性能下降,我們應(yīng)該想到的是如何按需禁用緩存和編譯優(yōu)化。

? Java內(nèi)存模型規(guī)范了JVM如何提供按需禁用緩存和編譯優(yōu)化的方法,這些方法包括volatile、synchronizedfinal三個(gè)關(guān)鍵字以及六項(xiàng)Happens-Before規(guī)則。

使用volatile困惑

volatile關(guān)鍵字在C語言也有,最原始的意義就是禁用CPU緩存。

例如:

volatile int x = 0

表達(dá)就是不能使用CPU緩存,必須從內(nèi)存中讀取或者寫入。

看起來沒啥問題,但是在實(shí)際使用卻會(huì)帶了困惑。

例如:

class VolatileExample {
  int x = 0;
  volatile boolean v = false;
  public void writer() {
    x = 42;
    v = true;
  }
  public void reader() {
    if (v == true) {
      System.out.println(x);
    }
  }
}

假如有A線程調(diào)用writer(),B線程調(diào)用reader(),輸出來的x會(huì)是多少呢,在JDK1.5之前,x可能是0或者42,這是因?yàn)镃PU緩存導(dǎo)致可見性問題,JDK1.5之后Java內(nèi)存模型對(duì)volatile語義進(jìn)行了增強(qiáng),因此就引出了Happens-Before規(guī)則。

Happens-Before規(guī)則

Happens-Before規(guī)則就是保證前面的一個(gè)操作的結(jié)果對(duì)后續(xù)操作是可見的。

它約束了編譯器的優(yōu)化行為,雖允許編譯器優(yōu)化,但是要求編譯器優(yōu)化后一定遵守Happens-Before規(guī)則:

規(guī)則一:程序的順序性規(guī)則

? 這條規(guī)則是指在一個(gè)線程中,按照程序順序,前面的操作 Happens-Before 于后續(xù)的任意操作。

這還是比較容易理解的,比如剛才那段示例代碼,按照程序的順序,第 6 行代碼 “x = 42;” Happens-Before 于第 7 行代碼 “v = true;”,這就是規(guī)則 1 的內(nèi)容,也比較符合單線程里面的思維:程序前面對(duì)某個(gè)變量的修改一定是對(duì)后續(xù)操作可見的。

規(guī)則二:volatile 變量規(guī)則

? 這條規(guī)則是指對(duì)一個(gè) volatile 變量的寫操作, Happens-Before 于后續(xù)對(duì)這個(gè) volatile 變量的讀操作,即對(duì)后面的讀操作可見。

規(guī)則三:傳遞性

? 這條規(guī)則是指如果A Happens-Before B,B Happens-Before C,那么 A Happens-Before C。

規(guī)則四:管程中鎖的規(guī)則

? 這條規(guī)則是指對(duì)一個(gè)鎖的解鎖Happens-Before于后續(xù)對(duì)這個(gè)鎖的加鎖。

? 管程是一種通用的同步原語,在Java中指的就是synchronized,synchronized是Java里對(duì)管程的實(shí)現(xiàn)。

tip: 在操作系統(tǒng)中,管程的定義如下: 管程是由一組數(shù)據(jù)以及定義在這組數(shù)據(jù)之上的對(duì)該組數(shù)據(jù)操作的操作組成的軟件模塊,稱之為管程。

基本特性:

1. 局部于管程的數(shù)據(jù)只能被局部于管程內(nèi)的過程所訪問。

2. 一個(gè)進(jìn)程只有通過調(diào)用管程內(nèi)的過程才能進(jìn)入管程訪問共享數(shù)據(jù)

3. 每次僅允許一個(gè)進(jìn)程在管程中執(zhí)行某個(gè)內(nèi)部過程。

注意:由于管程是一個(gè)語言的成分,所以管程的互斥訪問完全由編譯程序在編譯時(shí)自動(dòng)添加,無需程序員關(guān)注

? 管程中的鎖在Java是隱式實(shí)現(xiàn)的,加鎖以及釋放鎖都是編譯器幫我們實(shí)現(xiàn)的。

synchronized (this) { //此處自動(dòng)加鎖
 // x是共享變量,初始值=10
 if (this.x < 12) {
   this.x = 12; 
 }  
} //此處自動(dòng)解鎖

規(guī)則五:線程start()規(guī)則

? 這條是關(guān)于線程啟動(dòng)的,指主線程A啟動(dòng)子線程B后,子線程B能夠看到主線程在啟動(dòng)子線程B前的操作。

規(guī)則六:join()規(guī)則

? 這條是關(guān)于線程等待的,它是指主線程A等待子線程B完成(主線程A通過調(diào)用子線程B的join()方法實(shí)現(xiàn)),當(dāng)子線程B完成后(主線程A中join()方法返回)

主線程能夠看到子線程的操作。這里的“看到”,指的是對(duì)共享變量的操作。

通過調(diào)用子線程B的join()方法實(shí)現(xiàn)),當(dāng)子線程B完成后(主線程A中join()方法返回)

主線程能夠看到子線程的操作。這里的“看到”,指的是對(duì)共享變量的操作。

到此這篇關(guān)于關(guān)于Java中的可見性和有序性問題的文章就介紹到這了,更多相關(guān)Java可見性和有序性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java模擬微信搶紅包的實(shí)例代碼

    java模擬微信搶紅包的實(shí)例代碼

    現(xiàn)在搶紅包的功能很受歡迎,本篇文章主要介紹了java模擬微信搶紅包的實(shí)例代碼。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • 一文掌握SpringSecurity?BCrypt密碼加密和解密

    一文掌握SpringSecurity?BCrypt密碼加密和解密

    BCrypt就是一款加密工具,可以比較方便地實(shí)現(xiàn)數(shù)據(jù)的加密工作。也可以簡(jiǎn)單理解為它內(nèi)部自己實(shí)現(xiàn)了隨機(jī)加鹽處理,這篇文章主要介紹了SpringSecurity?BCrypt密碼加密和解密,一文學(xué)會(huì)使用BCryptPasswordEncoder的方法,需要的朋友可以參考下
    2023-04-04
  • 詳解SpringBoot啟動(dòng)代碼和自動(dòng)裝配源碼分析

    詳解SpringBoot啟動(dòng)代碼和自動(dòng)裝配源碼分析

    這篇文章主要介紹了SpringBoot啟動(dòng)代碼和自動(dòng)裝配源碼分析,使用SpringBoot很簡(jiǎn)單,在主類中添加一個(gè)@SpringBootApplication,以及調(diào)用SpringApplication.run()并傳入主類,本文通過示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • ConcurrentHashMap線程安全及實(shí)現(xiàn)原理實(shí)例解析

    ConcurrentHashMap線程安全及實(shí)現(xiàn)原理實(shí)例解析

    這篇文章主要介紹了ConcurrentHashMap線程安全及實(shí)現(xiàn)原理實(shí)例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 解決SpringBoot中MultipartResolver和ServletFileUpload的沖突問題

    解決SpringBoot中MultipartResolver和ServletFileUpload的沖突問題

    這篇文章主要介紹了解決SpringBoot中MultipartResolver和ServletFileUpload的沖突問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java 抽象類特點(diǎn)總結(jié)

    Java 抽象類特點(diǎn)總結(jié)

    在面向?qū)ο蟮母拍钪?,所有的?duì)象都是通過類來描繪的,但是反過來,并不是所有的類都是用來描繪對(duì)象的,如果一個(gè)類中沒有包含足夠的信息來描繪一個(gè)具體的對(duì)象,這樣的類就是抽象類
    2021-10-10
  • Java多線程程序中synchronized修飾方法的使用實(shí)例

    Java多線程程序中synchronized修飾方法的使用實(shí)例

    synchronized關(guān)鍵字主要北用來進(jìn)行線程同步,這里我們主要來演示Java多線程程序中synchronized修飾方法的使用實(shí)例,需要的朋友可以參考下:
    2016-06-06
  • springboot 多環(huán)境切換的方法

    springboot 多環(huán)境切換的方法

    這篇文章主要介紹了springboot 多環(huán)境切換的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 基于Beanutils.copyProperties()的用法及重寫提高效率

    基于Beanutils.copyProperties()的用法及重寫提高效率

    這篇文章主要介紹了Beanutils.copyProperties( )的用法及重寫提高效率的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • SpringBoot整合ES高級(jí)查詢方式

    SpringBoot整合ES高級(jí)查詢方式

    這篇文章主要介紹了SpringBoot整合ES高級(jí)查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05

最新評(píng)論