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

java volatile關(guān)鍵字作用及使用場(chǎng)景詳解

 更新時(shí)間:2019年08月04日 14:18:23   作者:孜然狼  
在本文里我們給大家分享的是關(guān)于java volatile關(guān)鍵字作用及使用場(chǎng)景的相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的朋友們學(xué)習(xí)下。

1. volatile關(guān)鍵字的作用:保證了變量的可見(jiàn)性(visibility)。被volatile關(guān)鍵字修飾的變量,如果值發(fā)生了變更,其他線程立馬可見(jiàn),避免出現(xiàn)臟讀的現(xiàn)象。如以下代碼片段,isShutDown被置為true后,doWork方法仍有執(zhí)行。如用volatile修飾isShutDown變量,可避免此問(wèn)題。

public class VolatileTest3 {
 static class Work {
 boolean isShutDown = false;

 void shutdown() {
  isShutDown = true;
  System.out.println("shutdown!");
 }

 void doWork() {
  while (!isShutDown) {
  System.out.println("doWork");
  }
 }
 }

 public static void main(String[] args) {
 Work work = new Work();

 new Thread(work::doWork).start();
 new Thread(work::doWork).start();
 new Thread(work::doWork).start();
 new Thread(work::shutdown).start();
 new Thread(work::doWork).start();
 new Thread(work::doWork).start();
 new Thread(work::doWork).start();
 }
}

出現(xiàn)臟讀時(shí),運(yùn)行結(jié)果如下:

2. 為什么會(huì)出現(xiàn)臟讀?

Java內(nèi)存模型規(guī)定所有的變量都是存在主存當(dāng)中,每個(gè)線程都有自己的工作內(nèi)存。線程對(duì)變量的所有操作都必須在工作內(nèi)存中進(jìn)行,而不能直接對(duì)主存進(jìn)行操作。并且每個(gè)線程不能訪問(wèn)其他線程的工作內(nèi)存。變量的值何時(shí)從線程的工作內(nèi)存寫回主存,無(wú)法確定。

3. happens-before規(guī)則的理解與勘誤

在網(wǎng)上查volatile關(guān)鍵字相關(guān)信息時(shí),多篇博客提到了happens-before原則,個(gè)人對(duì)此原則的理解是:當(dāng)操作該volatile變量時(shí),所有前序?qū)υ撟兞康牟僮鞫家淹瓿桑ㄈ绮淮嬖谝炎兏?,但未寫回主存的情況),所有后續(xù)對(duì)該變量的操作,都未開始。僅此而已。

這里,我認(rèn)為網(wǎng)上很常見(jiàn)的一個(gè)理論對(duì)此理解有誤,如下圖。此觀點(diǎn)認(rèn)為,由于volatile變量flag的happens-before原則,所以A線程2處對(duì)其的寫操作一定先于B線程3處對(duì)其的讀操作。其實(shí)這種觀點(diǎn)是有邏輯缺陷的,如果存在一個(gè)C線程,先讀取flag的值,后寫入flag的值,那C線程的執(zhí)行時(shí)機(jī)是什么呢?如果還有其他D、E線程呢。。。對(duì)于這段代碼的正確理解是,只要3處拿到的flag是true,那么a的值一定是1,而不是0.因?yàn)関olition修飾的變量,處理器不會(huì)對(duì)其進(jìn)行重排序,所以1處對(duì)a的賦值,一定發(fā)生在2處對(duì)flag的賦值之前。如果flag不是volatile變量,那么1處和2處代碼的執(zhí)行順序是無(wú)法保證的(處理器的指令重排序),雖然大部分情況1會(huì)先于2執(zhí)行。happens-before原則約束的并不是多線程對(duì)同一變量的讀和寫操作之間的順序,而是保證讀操作時(shí),前序所有對(duì)該變量的寫操作已生效(寫回主存)。

 

 

驗(yàn)證如下:

public class VolatileTest {
 static class A {
 int a = 0;
 volatile boolean flag = false;

 void writer() {
  a = 1;   //1
  flag = true;  //2
  System.out.println("write");
 }

 void reader() {
  if (flag) {  //3
  int i = a;  //4
  System.out.println("read true");
  System.out.println("i is :" + i);
  } else {
  int i = a;
  System.out.println("read false");
  System.out.println("i is :" + i);
  }
 }

 }

 public static void main(String[] args) {
 A aaa = new A();
 new Thread(() -> aaa.reader()).start();
 new Thread(() -> aaa.writer()).start();
 }
}

運(yùn)行結(jié)果如下,在寫操作執(zhí)行之前,讀操作已完成

 

 4. volatile關(guān)鍵字使用場(chǎng)景

注意:volatile只能保證變量的可見(jiàn)性,不能保證對(duì)volatile變量操作的原子性,見(jiàn)如下代碼:

public class VolatileTest2 {
 static class A {
 volatile int a = 0;
 void increase() {
  a++;
 }
 int getA(){
  return a;
 }
 }

 public static void main(String[] args) {
 A a = new A();

 new Thread(() -> {
  for (int i = 0;i < 1000;i++) {
  a.increase();
  }
  System.out.println(a.getA());
 }).start();
 new Thread(() -> {
  for (int i = 0;i < 2000;i++) {
  a.increase();
  }
  System.out.println(a.getA());
 }).start();
 new Thread(() -> {
  for (int i = 0;i < 3000;i++) {
  a.increase();
  }
  System.out.println(a.getA());
 }).start();
 new Thread(() -> {
  for (int i = 0;i < 4000;i++) {
  a.increase();
  }
  System.out.println(a.getA());
 }).start();
 new Thread(() -> {
  for (int i = 0;i < 5000;i++) {
  a.increase();
  }
  System.out.println(a.getA());
 }).start();
 }
}

運(yùn)行結(jié)果如下,volatile無(wú)法保證a++操作的原子性。

volatile正確的使用方法可參考:http://www.fzitv.net/article/166888.htm

以上就是本次介紹知識(shí)點(diǎn)的全部?jī)?nèi)容,感謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • java反射調(diào)用get/set方法實(shí)現(xiàn)

    java反射調(diào)用get/set方法實(shí)現(xiàn)

    本文文章介紹了在Java中使用反射調(diào)用get/set方法時(shí),如何通過(guò)Introspector和PropertyDescriptor來(lái)更優(yōu)雅地處理,下面就來(lái)詳細(xì)的介紹一下,感興趣的可以了解一下
    2025-12-12
  • Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解

    Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解

    這篇文章主要介紹了Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解,幫助大家更好的理解和使用springboot,感興趣的朋友可以了解下
    2021-02-02
  • String類的獲取功能、轉(zhuǎn)換功能

    String類的獲取功能、轉(zhuǎn)換功能

    這篇文章給大家介紹了String類的獲取功能:String類的基本獲取功能、獲取功能的舉例子、String類的基本轉(zhuǎn)換功能、轉(zhuǎn)換功能的舉例子。具體詳情大家參考下本文
    2018-04-04
  • 關(guān)于Java中的CAS如何使用

    關(guān)于Java中的CAS如何使用

    這篇文章主要介紹了關(guān)于Java中的CAS如何使用,CAS是Compare And Swap(比較并交換)的縮寫,是一種非阻塞式并發(fā)控制技術(shù),用于保證多個(gè)線程在修改同一個(gè)共享資源時(shí)不會(huì)出現(xiàn)競(jìng)爭(zhēng)條件,從而避免了傳統(tǒng)鎖機(jī)制的各種問(wèn)題,需要的朋友可以參考下
    2023-09-09
  • Spring配置文件解析之BeanDefinitionReader詳解

    Spring配置文件解析之BeanDefinitionReader詳解

    這篇文章主要介紹了Spring配置文件解析之BeanDefinitionReader詳解,ApplicationContext.xml配置文件解析成Document對(duì)象,真正對(duì)xml中元素解析的類是在BeanDefinitionDocumentReader的實(shí)現(xiàn)類中來(lái)完成的,需要的朋友可以參考下
    2024-02-02
  • Java死鎖產(chǎn)生原因及示例

    Java死鎖產(chǎn)生原因及示例

    本文主要介紹了Java死鎖產(chǎn)生原因及示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 基于JDBC封裝的BaseDao(實(shí)例代碼)

    基于JDBC封裝的BaseDao(實(shí)例代碼)

    下面小編就為大家?guī)?lái)一篇基于JDBC封裝的BaseDao(實(shí)例代碼)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-07-07
  • java  HttpServletRequest和HttpServletResponse詳解

    java HttpServletRequest和HttpServletResponse詳解

    這篇文章主要介紹了java HttpServletRequest和HttpServletResponse詳解的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • Mybatis的association使用子查詢結(jié)果錯(cuò)誤的問(wèn)題解決

    Mybatis的association使用子查詢結(jié)果錯(cuò)誤的問(wèn)題解決

    本文主要介紹了Mybatis的association使用子查詢結(jié)果錯(cuò)誤的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-07-07
  • 詳解Java集合類之HashSet篇

    詳解Java集合類之HashSet篇

    這篇文章主要為大家詳細(xì)介紹一下Java集合類中HashSet的用法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,感興趣的可以了解一下
    2022-07-07

最新評(píng)論

侯马市| 伽师县| 团风县| 东丽区| 泽库县| 同德县| 台山市| 德阳市| 德化县| 黑山县| 临武县| 孙吴县| 衡东县| 望谟县| 龙山县| 丹阳市| 平昌县| 旌德县| 噶尔县| 抚顺县| 苍山县| 南川市| 星座| 家居| 山东| 塔河县| 梅州市| 得荣县| 芦溪县| 商城县| 惠州市| 莒南县| 丰镇市| 兴安盟| 贡嘎县| 平安县| 明溪县| 松原市| 贵德县| 双桥区| 凤翔县|