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

Java線程安全之volatile詳解

 更新時(shí)間:2023年08月26日 09:19:42   作者:not coder  
這篇文章主要介紹了Java線程安全之volatile詳解,volatile 的存在,解決了不同內(nèi)存間拷貝的同步問題,在每一次使用或者修改時(shí)候,都去原持有內(nèi)存中去拿最新的狀態(tài),需要的朋友可以參考下

volatile

volatile 的存在,解決了不同內(nèi)存間拷貝的同步問題,在每一次使用或者修改時(shí)候,都去原持有內(nèi)存中去拿最新的狀態(tài)

或者說可以這樣理解,volatile 的修飾讓線程放棄了使用各自內(nèi)存的做法轉(zhuǎn)而使用共享內(nèi)存,從而保證了可靠性,但是降低了效率

所以說我們只在需要不同線程訪問同一個(gè)值的時(shí)候才去打開這個(gè)限制

第一種情況

首先我們來寫一個(gè)測試代碼

public class Synchronized1Test {
    private boolean running = true;
    public void runTest() {
        new Thread() {
            @Override
            public void run() {
                while (running) {
                    System.out.println("線程開始執(zhí)行,,,,");
                }
            }
        }.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        stop();
    }
    private void stop() {
        running = false;
    }
}

代碼大致要表達(dá)的是,主線程在一秒之后要調(diào)用 stop 方法將 running = false,這樣,子線程的死循環(huán)就會(huì)被打破,這樣子線程停止執(zhí)行,主線程也執(zhí)行完畢,整個(gè)程序結(jié)束。

但是實(shí)際的執(zhí)行結(jié)果是,子線程的死循環(huán)并不會(huì)結(jié)束,會(huì)一直不停的執(zhí)行下去

這是因?yàn)榫€程直接做變量的值的修改并不是直接改的,而是先拷貝一份到自己線程的內(nèi)存區(qū)域,更改完之后再適時(shí)同步給原持有此值的線程,這樣做的目的是提高程序的運(yùn)行效率

而在這里,主線程持有此變量,子線程在執(zhí)行時(shí)候,將值拷貝了一份到自己的內(nèi)存中,然后子線程并沒有做值的修改,并不存在將值同步給主線程的過程,而此值的持有線程是主線程,主線程在更改完此值之后只會(huì)同步給自己,并不會(huì)同步給子線程,所以說子線程的值永遠(yuǎn)為最初拷貝走的值,永遠(yuǎn)為true,就永遠(yuǎn)不會(huì)停下來了。

有一個(gè)關(guān)鍵字 volatile 能解決這個(gè)問題

public class Synchronized1Test {
    private volatile boolean running = true;
	.....
}

volatile 的存在,解決了不同內(nèi)存間拷貝的同步問題,在每一次使用或者修改時(shí)候,都去原持有內(nèi)存中去拿最新的狀態(tài),或者說可以這樣理解,volatile 的修飾讓線程放棄了使用各自內(nèi)存的做法轉(zhuǎn)而使用共享內(nèi)存,從而保證了可靠性,但是降低了效率,所以說我們只在需要不同線程訪問同一個(gè)值的時(shí)候才去打開這個(gè)限制

再次運(yùn)行,果然一秒結(jié)束

第二種情況

public class Synchronized2Test {
    private int x = 0;
    private void count() {
        x++;
    }
    public void runTest() {
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 1_000_000; i++) {
                    count();
                }
                System.out.println("x 在線程1的最終值" + x);
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 1_000_000; i++) {
                    count();
                }
                System.out.println("x 在線程2的最終值" + x);
            }
        }.start();
    }
}

從代碼來看,兩個(gè)線程分別對同一個(gè)數(shù)進(jìn)行一百萬次從自增操作,無論誰最后執(zhí)行完成,理論上來講,總有一個(gè)線程打印出來的結(jié)果是兩百萬,但實(shí)際的運(yùn)行效果,無論執(zhí)行多少次都沒有兩百萬的結(jié)果出來。

都是因?yàn)樯衔恼f的,值的同步性問題,在各自內(nèi)存區(qū)域修改完后適時(shí)同步回去,導(dǎo)致的這個(gè)問題

然后我們加上 volatile 關(guān)鍵字

public class Synchronized2Test {
    private volatile int x = 0;
	.....
}

運(yùn)行,還是不行,為啥啊,都加上了怎么還是不行呢?

這里主要的原因是因?yàn)?x++; 這個(gè)操作

在 Java 中, x++; 是兩步操作,不是原子操作,是可拆的操作

他的運(yùn)算過程大致相當(dāng)于是

int temp = x + 1;
	x = temp;

這樣,在代碼分為兩行執(zhí)行的時(shí)候,搶線程的操作就發(fā)生了,就出現(xiàn)了值異常的情況

到目前為止,線程安全除了加 volatile 關(guān)鍵字外,還需要保證會(huì)互相影響的操作合成一個(gè)原子操作

這里解釋一下原子操作,簡單來說,把多個(gè)步驟看成一個(gè)整體,要么你別執(zhí)行我,要么就完全執(zhí)行,不要在執(zhí)行一半時(shí)候發(fā)生線程切換

這里引入我們保證一塊代碼塊執(zhí)行原子操作的關(guān)鍵字:synchronized

這時(shí)候我們改一下我們的代碼,給 count 方法增加 synchronized 關(guān)鍵字,并且可以將 volatile 關(guān)鍵字去除了

public class Synchronized2Test {
    private int x = 0;
    private synchronized void count() {
        x++;
    }
    .....
}

運(yùn)行,果然順利的打印出來了兩百萬,多次運(yùn)行也是這個(gè)結(jié)果

受保護(hù)的類型

到此,我們講一下官方提供的原子型的類型,這里拿之前出現(xiàn)過的 AtomicInteger 舉例

AtomicInteger 對標(biāo)的就是 int,他是對 int 的包裝,可以保證 int 具有同步性和原子性

這里的同步性可以理解為上文提到的被 volatile 修飾,原子性可以理解為被 synchronized 修飾

例:

// 可以理解為默認(rèn)值為 0 的 int
AtomicInteger count  = new AtomicInteger(0);
// 相當(dāng)于是 ++count
count.incrementAndGet();
// 相當(dāng)于是 count++
count.getAndIncrement();

代碼中的 count.incrementAndGet() 相當(dāng)于是 ++count

count.getAndIncrement() 相當(dāng)于是 count++

除此之外還有

常規(guī)類型保護(hù)類型
intAtomicInteger
booleanAtomicBoolean
int[]AtomicIntegerArray
TAtomicReference< T>

不一一列舉

其中要說的就是 AtomicReference,他把傳入的范型,自動(dòng)幫我們做成了保護(hù)類型,使得在賦值和取值時(shí)候不出錯(cuò)

到此這篇關(guān)于Java線程安全之volatile詳解的文章就介紹到這了,更多相關(guān)Java的volatile內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis增強(qiáng)版MyBatis-Flex的具體使用

    Mybatis增強(qiáng)版MyBatis-Flex的具體使用

    Mybatis-Flex一個(gè)用于增強(qiáng)MyBatis的框架,本文主要介紹了Mybatis增強(qiáng)版MyBatis-Flex的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • 詳解Java數(shù)字簽名提供XML安全

    詳解Java數(shù)字簽名提供XML安全

    在本篇文章中我們給大家整理了關(guān)于Java數(shù)字簽名提供XML安全的知識點(diǎn)內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2018-08-08
  • Java?集合框架掌握?Map?和?Set?的使用(內(nèi)含哈希表源碼解讀及面試??碱})

    Java?集合框架掌握?Map?和?Set?的使用(內(nèi)含哈希表源碼解讀及面試常考題)

    這篇文章主要介紹了Java?集合框架掌握?Map?和?Set?的使用并含有內(nèi)含哈希表源碼解讀及面試??碱},?Map?和?Set?是一種適合動(dòng)態(tài)查找的集合容器或者數(shù)據(jù)結(jié)構(gòu)下面文章詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2021-12-12
  • Spring Boot中slf4j日志依賴關(guān)系示例詳解

    Spring Boot中slf4j日志依賴關(guān)系示例詳解

    在項(xiàng)目開發(fā)中,記錄日志是必做的一件事情。而當(dāng)我們使用Springboot框架時(shí),記錄日志就變得極其簡單了。下面這篇文章主要給大家介紹了關(guān)于Spring Boot中slf4j日志依賴關(guān)系的相關(guān)資料,需要的朋友可以參考下
    2018-11-11
  • Spring Boot 中 MyBatis 與 Spring Data JPA 的優(yōu)缺點(diǎn)對比

    Spring Boot 中 MyBatis 與 Spring 

    這篇文章主要介紹了Spring Boot 中 MyBatis 與 Spring Data JPA 的優(yōu)缺點(diǎn)對比,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-05-05
  • SpringBoot登錄、退出、獲取用戶信息的session處理方案

    SpringBoot登錄、退出、獲取用戶信息的session處理方案

    這篇文章主要介紹了SpringBoot登錄、退出、獲取用戶信息的session處理,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • 深入理解Java注解類型(@Annotation)

    深入理解Java注解類型(@Annotation)

    這篇文章主要介紹了深入理解Java注解類型(@Annotation),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • Java SE使用數(shù)組實(shí)現(xiàn)高速數(shù)字轉(zhuǎn)換功能

    Java SE使用數(shù)組實(shí)現(xiàn)高速數(shù)字轉(zhuǎn)換功能

    隨著大數(shù)據(jù)時(shí)代的到來,數(shù)字轉(zhuǎn)換功能變得越來越重要,在Java開發(fā)中,數(shù)字轉(zhuǎn)換功能也是經(jīng)常用到的,下面我們就來學(xué)習(xí)一下如何使用Java SE數(shù)組實(shí)現(xiàn)高速的數(shù)字轉(zhuǎn)換功能吧
    2023-11-11
  • 一文詳解如何使用Java打造更優(yōu)雅的AI代理

    一文詳解如何使用Java打造更優(yōu)雅的AI代理

    在人工智能(AI)代理開發(fā)的浪潮中,Python似乎一直是默認(rèn)的編程語言選擇,本文將深入探索Java如何以更少的代碼和更高的可擴(kuò)展性創(chuàng)造出更高效,更優(yōu)雅的AI代理,希望對大家有所幫助
    2025-10-10
  • Java類的初始化順序的實(shí)現(xiàn)

    Java類的初始化順序的實(shí)現(xiàn)

    類的初始化過程是在類加載階段完成的,包括加載、驗(yàn)證、準(zhǔn)備、解析和初始化等步驟,本文主要介紹了Java類的初始化順序的實(shí)現(xiàn),感興趣的可以了解一下
    2023-12-12

最新評論

南丰县| 新安县| 珲春市| 米脂县| 龙口市| 三亚市| 拜城县| 茌平县| 西和县| 定州市| 开远市| 三亚市| 靖远县| 河间市| 剑河县| 柘城县| 澳门| 保定市| 洛川县| 永州市| 普格县| 荥阳市| 连城县| 兰州市| 长春市| 沅陵县| 温宿县| 多伦县| 平果县| 昆山市| 双桥区| 喀喇| 商丘市| 乐都县| 云林县| 吉安市| 沧源| 葫芦岛市| 临沂市| 邵阳市| 临沭县|