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

Java volatile關鍵字特性講解上篇

 更新時間:2022年12月12日 15:52:09   作者:愛吃南瓜糕的北絡  
JMM要求保證可見性、原子性、有序性,volatile可以保證其中的兩個,本篇文章具體驗證volatile的可見性,不原子性和禁重排,同時解決volatile的不保證原子性,讓代碼具有原子性

一、概述

volatile是Java中的關鍵字,用來修飾會被不同線程訪問和修改的變量。

volatile是Java虛擬機提供的輕量級的同步機制,它有三個特性:

(1)保證可見性

(2)不保證原子性

(3)禁止指令重排

二、特性詳解

volatile保證可見性

Java內(nèi)存模型(JMM)定義了一組規(guī)則、規(guī)范,規(guī)定了程序中各個變量的訪問方法。JMM關于同步的規(guī)定:

(1)線程解鎖前,必須把共享變量的值刷新回主內(nèi)存;

(2)線程加鎖前,必須讀取主內(nèi)存的最新值同步到自己的工作內(nèi)存;

(3)加鎖解鎖必須是同一把鎖;

說明:由于JVM運行程序的實體是線程,創(chuàng)建每個線程時,JMM會為其創(chuàng)建一個工作內(nèi)存(也稱??臻g),工作內(nèi)存是每個線程的私有數(shù)據(jù)區(qū)域。

Java內(nèi)存模型規(guī)定所有變量都存儲在主內(nèi)存,主內(nèi)存是共享內(nèi)存區(qū)域,所有線程都可以訪問。

但是線程對變量的操作(讀取、賦值等)必須在工作內(nèi)存中進行。因此首先要將變量從主內(nèi)存拷貝到自己的工作內(nèi)存,然后對變量進行操作,操作完成后再將變量寫會主內(nèi)存中。

舉例說明:

(1)火車票賣票系統(tǒng)還剩下一張票,并已經(jīng)刷入到主內(nèi)存中:ticketNum = 1;

(2)此時有3個用戶在同時購買票,3個線程都讀入了目前的票數(shù),ticketNum=1,那么線程就會繼續(xù)進入購買流程。

(3)假設其中一個線程先搶占了CPU資源,先買到票,并將自己的工作內(nèi)存中的ticketNum值改為0,ticketNum=0,然后再寫回到主內(nèi)存。

這時,由于一個線程的用戶已經(jīng)買到了票,那么其他用戶的線程應該不能再繼續(xù)進入購買票的流程了,因此需要系統(tǒng)通知到其他線程 ticketNum=0 這個消息。如果可以達到這樣的效果,可以理解為 具有可見性。

無可見性代碼演示:

@Test
public void test1() {
    DataDemo dataDemo = new DataDemo();
    RunThread runThread = new RunThread(dataDemo);
    runThread.start();
    while (dataDemo.getNumber() == 0) {
    }
    System.out.println("具有可見性驗證通過");
}
public class DataDemo {
    private int number = 0;
    public void add() {
        this.number = this.number + 10;
    }
    public int getNumber() {
        return number;
    }
}
public class RunThread extends Thread {
    private DataDemo dataDemo;
    public RunThread(DataDemo dataDemo) {
        this.dataDemo = dataDemo;
    }
    @Override
    public void run() {
        System.out.println("線程[" + Thread.currentThread().getName() + "] 正在執(zhí)行");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dataDemo.add();
        System.out.println("線程[" + Thread.currentThread().getName() + "]更新后,number值為:" + dataDemo.getNumber());
    }
}

執(zhí)行結果:
線程[Thread-0] 正在執(zhí)行
線程[Thread-0]更新后,number值為:10

結果分析:

可以看出子線程啟動后將number值改為了10,雖然已經(jīng)改為了非0,但是主線程仍然一直處于while循環(huán)中,因此此時number不具有可見性,系統(tǒng)不會主動通知主線程number值修改。

原理說明:

這個問題其實就是私有堆棧中的值和公共堆棧中的值不同步造成的。解決這樣的問題就要使用 volatile 關鍵字了,它主要的作用就是當線程訪問number這個變量時,強制性從公共堆棧中進行取值。

可見性代碼演示:

@Test
public void test1() {
    DataDemo dataDemo = new DataDemo();
    RunThread runThread = new RunThread(dataDemo);
    runThread.start();
    while (dataDemo.getNumber() == 0) {
    }
    System.out.println("具有可見性驗證通過");
}
public class DataDemo {
    // 給變量 number 添加 volatile 關鍵字修飾
    volatile private int number = 0;
    public void add() {
        this.number = this.number + 10;
    }
    public int getNumber() {
        return number;
    }
}
public class RunThread extends Thread {
    private DataDemo dataDemo;
    public RunThread(DataDemo dataDemo) {
        this.dataDemo = dataDemo;
    }
    @Override
    public void run() {
        System.out.println("線程[" + Thread.currentThread().getName() + "] 正在執(zhí)行");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dataDemo.add();
        System.out.println("線程[" + Thread.currentThread().getName() + "]更新后,number值為:" + dataDemo.getNumber());
    }
}

執(zhí)行結果:
線程[Thread-0] 正在執(zhí)行
線程[Thread-0]更新后,number值為:10
具有可見性驗證通過

結果分析:

通過對變量number變量添加了volatile關鍵字修飾,可以看出子線程啟動后將number值改為了10,隨后主線程跳出了while循環(huán),輸出了“具有可見性驗證通過”,說明此時number具有可見性。

原理說明:

通過使用 volatile 關鍵字,強制從公共內(nèi)存中讀取變量的值,內(nèi)存結構如圖:

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

相關文章

  • 解決spring-data-jpa 事物中修改屬性自動更新update問題

    解決spring-data-jpa 事物中修改屬性自動更新update問題

    這篇文章主要介紹了解決spring-data-jpa 事物中修改屬性自動更新update問題,具有很好的參考價值,希望對大家
    2021-08-08
  • SpringBoot實現(xiàn)對Http接口進行監(jiān)控的代碼

    SpringBoot實現(xiàn)對Http接口進行監(jiān)控的代碼

    Spring Boot Actuator是Spring Boot提供的一個模塊,用于監(jiān)控和管理Spring Boot應用程序的運行時信息,本文將介紹一下Spring Boot Actuator以及代碼示例,以及如何進行接口請求監(jiān)控,需要的朋友可以參考下
    2024-07-07
  • 詳解UDP協(xié)議格式及在java中的使用

    詳解UDP協(xié)議格式及在java中的使用

    這篇文章主要介紹了UDP協(xié)議格式及在java中的使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • Java的HashSet源碼詳解

    Java的HashSet源碼詳解

    這篇文章主要介紹了Java的HashSet源碼詳解,HashSet底層封裝的是HashMap,所以元素添加會放到HashMap的key中,value值使用new Object對象作為value,所以HashSet和HashMap的所具有的特點是類似的,需要的朋友可以參考下
    2023-09-09
  • java?Springboot對接開發(fā)微信支付詳細流程

    java?Springboot對接開發(fā)微信支付詳細流程

    最近要做一個微信小程序,需要微信支付,所以研究了下怎么在java上集成微信支付功能,下面這篇文章主要給大家介紹了關于java?Springboot對接開發(fā)微信支付的相關資料,需要的朋友可以參考下
    2024-08-08
  • java的IO流詳細解讀

    java的IO流詳細解讀

    這篇文章主要介紹了java的IO流詳細解讀,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • springboot整合swagger3和knife4j的詳細過程

    springboot整合swagger3和knife4j的詳細過程

    knife4j的前身是swagger-bootstrap-ui,取名knife4j是希望她能像一把匕首一樣小巧,輕量,并且功能強悍,下面這篇文章主要介紹了springboot整合swagger3和knife4j的詳細過程,需要的朋友可以參考下
    2022-11-11
  • 圖文詳解MyEclipse更換背景主題的方法

    圖文詳解MyEclipse更換背景主題的方法

    今天小編就為大家分享一篇關于MyEclipse更換背景主題的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • java實現(xiàn)ModbusCRC16校驗的示例代碼

    java實現(xiàn)ModbusCRC16校驗的示例代碼

    本文介紹了使用Java實現(xiàn)ModbusCRC16校驗,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-11-11
  • Postman實現(xiàn)傳List<String>集合

    Postman實現(xiàn)傳List<String>集合

    這篇文章主要介紹了Postman實現(xiàn)傳List<String>集合方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論

马公市| 辽宁省| 巴南区| 西吉县| 舟山市| 灵武市| 榆中县| 华阴市| 彩票| 鄂托克前旗| 陆丰市| 米脂县| 五家渠市| 米脂县| 平泉县| 丽江市| 桃江县| 特克斯县| 福海县| 胶南市| 孟连| 城固县| 新绛县| 南阳市| 永仁县| 阳朔县| 石屏县| 浮山县| 阳信县| 山东省| 津市市| 玉溪市| 广汉市| 左贡县| 北宁市| 科技| 平阳县| 大连市| 福海县| 武汉市| 屯昌县|