亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java原子變量類(lèi)常見(jiàn)問(wèn)題解決

 更新時(shí)間:2020年03月13日 10:51:41   作者:yuanyb  
這篇文章主要介紹了Java原子變量類(lèi)常見(jiàn)問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

在學(xué)習(xí)多線程時(shí),遇到了原子變量類(lèi),它是基于 CAS 和 volatile 實(shí)現(xiàn)的,能夠保障對(duì)共享變量進(jìn)行 read-modify-write 更新操作的原子性和可見(jiàn)性。于是我就寫(xiě)了一段代碼試試,自認(rèn)為非常正確。

public class Test{
  private static AtomicInteger ID = new AtomicInteger(0);
  public static int nextID(){ //返回的ID范圍為 1~100
    if(ID.get() == 100) { //ID到達(dá)100時(shí),則從1開(kāi)始
      ID.set(1);
      return ID.get(); // return ID = 1;
    }
    else
      return ID.incrementAndGet(); //++ID
  }
  public static void main(String[] args) throws Exception{
    for(int i = 0; i < 5; i++){
      new Thread(()->{
        for(int j = 0; j < 100; j++)
          nextID();
      }).start();
    }
    Thread.sleep(1000); //應(yīng)該輸出100才對(duì)
    System.out.println(ID);
  }
}

用五個(gè)線程并發(fā)獲得ID,每個(gè)線程獲取100個(gè),最后應(yīng)該輸出100才是,但試了好幾次都不是100。原子變量類(lèi)不是能保障原子性和可見(jiàn)性嗎,為什么出現(xiàn)了競(jìng)態(tài)?

糾結(jié)了很久,還是很懵逼。后來(lái)發(fā)現(xiàn) get 方法相當(dāng)于讀取一個(gè) volatile 變量,而讀取一個(gè) volatile 變量時(shí),不具備排他性!(AtomicInteger類(lèi)內(nèi)部使用了volatile修飾了value值,而volatile關(guān)鍵字不具備排他性)

也就是說(shuō),當(dāng)一個(gè)線程剛讀取到了共享的 volatile 變量的值時(shí),其他線程可會(huì)馬上對(duì)共享變量進(jìn)行修改。如,線程A讀取到ID的值為99時(shí)(還沒(méi)對(duì)ID進(jìn)行修改),其他線程可能馬上就將ID加1了,此時(shí)共享變量為100了,其他線程再獲取ID時(shí),應(yīng)該令I(lǐng)D=1才是,但線程A已經(jīng)進(jìn)入了else分支,它還認(rèn)為ID=99,而不知道其他線程剛把ID加1變成了100,所以會(huì)吧ID加上1變成了101,這就出現(xiàn)了競(jìng)態(tài)。

《Java多線程編程實(shí)戰(zhàn)指南 - 核心篇》中,作者說(shuō):“可見(jiàn)性的保障僅僅意味著一個(gè)線程能夠讀取到共享變量的相對(duì)新值,而不能保障該線程能讀取到相應(yīng)變量的最新值”。如volatile對(duì)可見(jiàn)性的保障就是保障的相對(duì)新值,由于volatile不具備排他性,所以有可能讀線程剛讀到一個(gè)相對(duì)新值,寫(xiě)線程就更改了共享變量,此時(shí),讀線程剛剛讀取到的相對(duì)新值就不是最新的了。

作者對(duì)相對(duì)新值和最新值的定義:

對(duì)于同一個(gè)共享變量而言,一個(gè)線程更新了該變量的值之后,其他線程能夠讀取到這個(gè)更新后的值,那這個(gè)值就被稱(chēng)為該變量的 相對(duì)新值。

如果讀取這個(gè)共享變量的線程在讀取并使用該變量的時(shí)候其他線程無(wú)法更新該變量的值,那么該線程讀取到的相對(duì)新值就被稱(chēng)為該變量的 最新值。需要加鎖,才能讀取到最新值。

解決辦法,使用原子操作 compareAndSet:

private static int nextID(){ //返回的ID范圍為 1~100
  ID.compareAndSet(100, 0);
  return ID.incrementAndGet();
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解使用IntelliJ IDEA 配置Maven(入門(mén))

    詳解使用IntelliJ IDEA 配置Maven(入門(mén))

    本篇文章主要介紹了詳解使用IntelliJ IDEA 配置Maven(入門(mén)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • eclipse創(chuàng)建springboot項(xiàng)目的三種方式總結(jié)

    eclipse創(chuàng)建springboot項(xiàng)目的三種方式總結(jié)

    這篇文章主要介紹了eclipse創(chuàng)建springboot項(xiàng)目的三種方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java之TreeSet和TreeMap的兩種排序方式解讀

    Java之TreeSet和TreeMap的兩種排序方式解讀

    這篇文章主要介紹了Java之TreeSet和TreeMap的兩種排序方式解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 解讀Java中Set真的是無(wú)序的嗎

    解讀Java中Set真的是無(wú)序的嗎

    這篇文章主要介紹了Java中Set是不是無(wú)序的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • SpringBoot深入淺出分析初始化器

    SpringBoot深入淺出分析初始化器

    這篇文章主要介紹了SpringBoot初始化器的分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Maven包沖突導(dǎo)致NoSuchMethodError錯(cuò)誤的解決辦法

    Maven包沖突導(dǎo)致NoSuchMethodError錯(cuò)誤的解決辦法

    web 項(xiàng)目 能正常編譯,運(yùn)行時(shí)也正常啟動(dòng),但執(zhí)行到需要調(diào)用 org.codehaus.jackson 包中的某個(gè)方法時(shí),產(chǎn)生運(yùn)行異常,這篇文章主要介紹了Maven包沖突導(dǎo)致NoSuchMethodError錯(cuò)誤的解決辦法,需要的朋友可以參考下
    2024-05-05
  • 淺談Java方法的重載

    淺談Java方法的重載

    方法重載是指在一個(gè)類(lèi)中定義多個(gè)同名的方法,但要求每個(gè)方法具有不同的參數(shù)的類(lèi)型或參數(shù)的個(gè)數(shù)。調(diào)用重載方法時(shí),Java編譯器能通過(guò)檢查調(diào)用的方法的參數(shù)類(lèi)型和個(gè)數(shù)選擇一個(gè)恰當(dāng)?shù)姆椒?。方法重載通常用于創(chuàng)建完成一組任務(wù)相似但參數(shù)的類(lèi)型或參數(shù)的個(gè)數(shù)不同的方法。
    2016-04-04
  • Java中使用byte[]獲取16位字符串的技巧分享

    Java中使用byte[]獲取16位字符串的技巧分享

    在Java編程中,處理字符編碼和字節(jié)數(shù)組時(shí),尤其是從??byte[]???數(shù)組中獲取字符串,可能會(huì)遇到字符集的復(fù)雜性問(wèn)題,本文將介紹如何從一個(gè)??byte[]??數(shù)組中正確獲取16位字符串,需要的朋友可以參考下
    2024-08-08
  • springboot中自定義異常以及定制異常界面實(shí)現(xiàn)過(guò)程解析

    springboot中自定義異常以及定制異常界面實(shí)現(xiàn)過(guò)程解析

    這篇文章主要介紹了springboot中自定義異常以及定制異常界面實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Java將一個(gè)正整數(shù)分解質(zhì)因數(shù)的代碼

    Java將一個(gè)正整數(shù)分解質(zhì)因數(shù)的代碼

    這篇文章主要介紹了將一個(gè)正整數(shù)分解質(zhì)因數(shù)。例如:輸入90,打印出90=2*3*3*5,需要的朋友可以參考下
    2017-02-02

最新評(píng)論