最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳細(xì)談?wù)凧ava中l(wèi)ong和double的原子性

 更新時(shí)間:2021年08月26日 09:40:25   作者:LouisWong  
原子性是指一個(gè)操作或多個(gè)操作要么全部執(zhí)行,且執(zhí)行的過程不會(huì)被任何因素打斷,要么就都不執(zhí)行,下面這篇文章主要給大家介紹了關(guān)于Java中l(wèi)ong和double原子性的相關(guān)資料,需要的朋友可以參考下

前言

java中基本類型中,long和double的長度都是8個(gè)字節(jié),32位(4字節(jié))處理器對(duì)其讀寫操作無法一次完成,那么,JVM,long和double是原子性的嗎?

JVM中對(duì)long的操作是不是原子操作?

首先,通過一段程序?qū)ong的原子性進(jìn)行判斷。測(cè)試程序如下:

public class LongAtomTest implements Runnable {

    private static long field = 0;

    private volatile long value;

    public long getValue() {
        return value;
    }

    public void setValue(long value) {
        this.value = value;
    }

    public LongAtomTest(long value) {
        this.setValue(value);
    }

    @Override
    public void run() {
        int i = 0;
        while (i < 100000) {
            LongAtomTest.field = this.getValue();
            i++;
            long temp = LongAtomTest.field;
            if (temp != 1L && temp != -1L) {
                System.out.println("出現(xiàn)錯(cuò)誤結(jié)果" + temp);
                System.exit(0);
            }
        }
        System.out.println("運(yùn)行正確");
    }

    public static void main(String[] args) throws InterruptedException {
        // 獲取并打印當(dāng)前JVM是32位還是64位的
        String arch = System.getProperty("sun.arch.data.model");
        System.out.println(arch+"-bit");
        LongAtomTest t1 = new LongAtomTest(1);
        LongAtomTest t2 = new LongAtomTest(-1);
        Thread T1 = new Thread(t1);
        Thread T2 = new Thread(t2);
        T1.start();
        T2.start();
        T1.join();
        T2.join();
    }

}

可以看到,程序中有兩條線程t1,t2; t1,t2各自不停的給long類型的靜態(tài)變量field賦值為1,-1; t1,t2每次賦值后,會(huì)讀取field的值,若field值既不是1又不是-1,就將field的值打印出來

如果對(duì)long的寫入和讀取操作是原子性的,那么,field的值只可能是1或者-1

運(yùn)行結(jié)果如下

32-bit
出現(xiàn)錯(cuò)誤結(jié)果-4294967295
運(yùn)行正確

可以看出,當(dāng)線程t1,t2同時(shí)對(duì)long進(jìn)行寫的時(shí)候,long出現(xiàn)了既不是t1寫入的值,又不是t2寫入的值??梢酝茰y(cè),jvm中對(duì)long的操作并非原子操作。

為什么對(duì)long的操作不是原子的?

JVM內(nèi)存模型中定義了8中原子操作:

  1. lock:將一個(gè)變量標(biāo)識(shí)為被一個(gè)線程獨(dú)占狀態(tài)
  2. unclock:將一個(gè)變量從獨(dú)占狀態(tài)釋放出來,釋放后的變量才可以被其他線程鎖定
  3. read:將一個(gè)變量的值從主內(nèi)存?zhèn)鬏數(shù)焦ぷ鲀?nèi)存中,以便隨后的load操作
  4. load:把read操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量的副本中
  5. use:把工作內(nèi)存中的一個(gè)變量的值傳給執(zhí)行引擎,每當(dāng)虛擬機(jī)遇到一個(gè)使用到變量的指令時(shí)都會(huì)使用該指令
  6. assign:把一個(gè)從執(zhí)行引擎接收到的值賦給工作內(nèi)存中的變量,每當(dāng)虛擬機(jī)遇到一個(gè)給變量賦值的指令時(shí),都要使用該操作
  7. store:把工作內(nèi)存中的一個(gè)變量的值傳遞給主內(nèi)存,以便隨后的write操作
  8. write:把store操作從工作內(nèi)存中得到的變量的值寫到主內(nèi)存中的變量

其中,與賦值,取值相關(guān)的包括 read,load,use,assign,store,write

按照這個(gè)規(guī)定,long的讀寫都是原子操作,與我們的實(shí)踐結(jié)果相反,為什會(huì)導(dǎo)致這種問題呢?

對(duì)于32位操作系統(tǒng)來說,單次次操作能處理的最長長度為32bit,而long類型8字節(jié)64bit,所以對(duì)long的讀寫都要兩條指令才能完成(即每次讀寫64bit中的32bit)。如果JVM要保證long和double讀寫的原子性,勢(shì)必要做額外的處理。 那么,JVM有對(duì)這一情況進(jìn)行額外處理嗎? 針對(duì)這一問題可以參考Java語言規(guī)范文檔:jls-17 Non-Atomic Treatment of double and long

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.

Some implementations may find it convenient to divide a single write action on a 64-bit long or double value into two write actions on adjacent 32-bit values. For efficiency's sake, this behavior is implementation-specific; an implementation of the Java Virtual Machine is free to perform writes to long and double values atomically or in two parts.

Implementations of the Java Virtual Machine are encouraged to avoid splitting 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.

從規(guī)定中我們可以知道

  1. 對(duì)于64位的long和double,如果沒有被volatile修飾,那么對(duì)其操作可以不是原子的。在操作的時(shí)候,可以分成兩步,每次對(duì)32位操作。
  2. 如果使用volatile修飾long和double,那么其讀寫都是原子操作
  3. 對(duì)于64位的引用地址的讀寫,都是原子操作
  4. 在實(shí)現(xiàn)JVM時(shí),可以自由選擇是否把讀寫long和double作為原子操作
  5. 推薦JVM實(shí)現(xiàn)為原子操作

從程序得到的結(jié)果來看,32位的HotSpot沒有把long和double的讀寫實(shí)現(xiàn)為原子操作。 在讀寫的時(shí)候,分成兩次操作,每次讀寫32位。因?yàn)椴捎昧诉@種策略,所以64位的long和double的讀與寫都不是原子操作。

在硬件,操作系統(tǒng),JVM都是64位的情況下呢?

對(duì)于64bit的環(huán)境來說,單次操作可以操作64bit的數(shù)據(jù),即可以以一次性讀寫long或double的整個(gè)64bit。因此我們可以猜測(cè),在64位的環(huán)境下,long和double的讀寫有可能是原子操作。 在換了64位的JVM之后,多次運(yùn)行,結(jié)果都是正確的

64-bit
運(yùn)行正確
運(yùn)行正確

結(jié)果表明,在64bit的虛擬機(jī)下,long的處理是原子性的。

總結(jié)

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

相關(guān)文章

  • Spring中的BeanDefinition注冊(cè)流程詳解

    Spring中的BeanDefinition注冊(cè)流程詳解

    這篇文章主要介紹了Spring中的BeanDefinition注冊(cè)流程詳解,  NamespaceHandler簡單來說就是命名空間處理器,Spring為了開放性提供了NamespaceHandler機(jī)制,這樣我們就可以根據(jù)需求自己來處理我們?cè)O(shè)置的標(biāo)簽元素,需要的朋友可以參考下
    2023-12-12
  • Hadoop2.8.1完全分布式環(huán)境搭建過程

    Hadoop2.8.1完全分布式環(huán)境搭建過程

    本文搭建了一個(gè)由三節(jié)點(diǎn)(master、slave1、slave2)構(gòu)成的Hadoop完全分布式集群(區(qū)別單節(jié)點(diǎn)偽分布式集群),并通過Hadoop分布式計(jì)算的一個(gè)示例測(cè)試集群的正確性。對(duì)hadoop分布式環(huán)境搭建過程感興趣的朋友跟隨小編一起看看吧
    2019-06-06
  • Springboot整合zookeeper實(shí)現(xiàn)對(duì)節(jié)點(diǎn)的創(chuàng)建、監(jiān)聽與判斷的案例詳解

    Springboot整合zookeeper實(shí)現(xiàn)對(duì)節(jié)點(diǎn)的創(chuàng)建、監(jiān)聽與判斷的案例詳解

    這篇文章主要介紹了基于Springboot整合zookeeper實(shí)現(xiàn)對(duì)節(jié)點(diǎn)的創(chuàng)建、監(jiān)聽與判斷,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 淺析Java編程中枚舉類型的定義與使用

    淺析Java編程中枚舉類型的定義與使用

    這篇文章主要介紹了Java編程中枚舉類型的定義與使用,簡單講解了enum關(guān)鍵字與枚舉類的用法,需要的朋友可以參考下
    2016-05-05
  • MyBatis利用MyCat實(shí)現(xiàn)多租戶的簡單思路分享

    MyBatis利用MyCat實(shí)現(xiàn)多租戶的簡單思路分享

    這篇文章主要給大家介紹了關(guān)于MyBatis利用MyCat實(shí)現(xiàn)多租戶的簡單思路的相關(guān)資料,文中的多租戶是基于多數(shù)據(jù)庫進(jìn)行實(shí)現(xiàn)的,數(shù)據(jù)是通過不同數(shù)據(jù)庫進(jìn)行隔離,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-06-06
  • Java中Redis存儲(chǔ)String類型會(huì)有亂碼的問題及解決方案

    Java中Redis存儲(chǔ)String類型會(huì)有亂碼的問題及解決方案

    在java中使用Redis存儲(chǔ)String類型的數(shù)據(jù)時(shí),會(huì)出現(xiàn)亂碼,我寫了一條存儲(chǔ)key為name,值為虎哥的字符串,然后獲取一下這個(gè)key為name的值,打印得到的值,下面通過實(shí)例代碼介紹Java中Redis存儲(chǔ)String類型會(huì)有亂碼的問題及解決方案,一起看看吧
    2024-04-04
  • Java 通過mave命令下載jar包的示例代碼

    Java 通過mave命令下載jar包的示例代碼

    這篇文章主要介紹了Java 通過mave命令下載jar的示例代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • java設(shè)計(jì)模式之簡單工廠模式詳解

    java設(shè)計(jì)模式之簡單工廠模式詳解

    這篇文章主要介紹了java設(shè)計(jì)模式之簡單工廠模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Java高級(jí)面試題小結(jié)

    Java高級(jí)面試題小結(jié)

    本文主要介紹了一些在Java面試過程中的一些高級(jí)面試題,包括對(duì)部分名詞的釋義及代碼解析,具有一定收藏價(jià)值,需要的朋友可以參考下
    2017-09-09
  • Spring通過配置文件管理Bean對(duì)象的方法

    Spring通過配置文件管理Bean對(duì)象的方法

    這篇文章主要介紹了Spring通過配置文件管理Bean對(duì)象的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07

最新評(píng)論

阿勒泰市| 申扎县| 东丰县| 瓮安县| 张家口市| 宜黄县| 从化市| 滨海县| 滦南县| 祁东县| 行唐县| 临颍县| 凉山| 石棉县| 桂东县| 桐乡市| 岐山县| 六盘水市| 永定县| 庆云县| 乐业县| 林西县| 永济市| 清流县| 格尔木市| 新建县| 罗定市| 永川市| 克拉玛依市| 龙江县| 屯留县| 沁水县| 边坝县| 兴仁县| 区。| 白河县| 石家庄市| 彰化县| 延长县| 大邑县| 长乐市|