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

談談Java中Volatile關鍵字的理解

 更新時間:2016年03月30日 16:39:21   作者:小眼兒  
volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程序中使用它往往會導致出人意料的結果,本文給大家介紹java中volatile關鍵字,需要的朋友參考下

volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程序中使用它往往會導致出人意料的結果。在Java 5之后,volatile關鍵字才得以重獲生機。volatile關鍵字雖然從字面上理解起來比較簡單,但是要用好不是一件容易的事情。

一、前言

  JMM提供了volatile變量定義、final、synchronized塊來保證可見性。
  用volatile修飾的變量,線程在每次使用變量的時候,都會讀取變量修改后的最的值。volatile很容易被誤用,用來進行原子性操作。寫了幾個測試的例子,大家可以試一試。

二、主程序

public class Main{
public static void main(String[] args) throws InterruptedException{
List<Thread> threadList = new ArrayList<Thread>();
for(int i=0; i<10; ++i){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Single.Holder.instance.add();
}
});
threadList.add(thread);
thread.start();
}
for(Thread thread : threadList)
thread.join();
System.out.println(Single.Holder.instance.x);
}
}

三、單例模式測試

  1、沒有volatile,沒有synchronized的情況   

class Single{
public int x = 0;
public void add(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
++this.x;
}
public static class Holder{
public static Single instance = new Single();
}
} 

    輸出結果:8, 9, 10都出現(xiàn)過??梢远噙\行,多試一試,就會發(fā)現(xiàn)不同的結果。

  2、有volatile,沒有synchronized

class Single{
public volatile int x = 0;
public void add(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
++this.x;
}
public static class Holder{
public static Single instance = new Single();
}
}

    輸出結果:最多出現(xiàn)的是9 和 10。

  3、沒有volatile,有synchronized

class Single{
public int x = 0;
public synchronized void add(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
++this.x;
}
public static class Holder{
public static Single instance = new Single();
}
}

  輸出結果:無論運行多少次都是10。

四、關于volatile在DCL(double check lock)中的應用

public class LazySingleton {
private int someField;
private static LazySingleton instance;
private LazySingleton() {
this.someField = new Random().nextInt(200)+1; // (1)
}
public static LazySingleton getInstance() {
if (instance == null) { // (2)
synchronized(LazySingleton.class) { // (3)
if (instance == null) { // (4)
instance = new LazySingleton(); // (5)
}
}
}
return instance; // (6)
}
public int getSomeField() {
return this.someField; // (7)
}
}

  首先說明一下,為什么這種寫法在java中是行不通的!

  假設線程Ⅰ是初次調用getInstance()方法,緊接著線程Ⅱ也調用了getInstance()方法和getSomeField()方法,我們要說明的是線程Ⅰ的語句(1)并不happen-before線程Ⅱ的語句(7)。線程Ⅱ在執(zhí)行getInstance()方法的語句(2)時,由于對instance的訪問并沒有處于同步塊中,因此線程Ⅱ可能觀察到也可能觀察不到線程Ⅰ在語句(5)時對instance的寫入,也就是說instance的值可能為空也可能為非空。我們先假設instance的值非空,也就觀察到了線程Ⅰ對instance的寫入,這時線程Ⅱ就會執(zhí)行語句(6)直接返回這個instance的值,然后對這個instance調用getSomeField()方法,該方法也是在沒有任何同步情況被調用,因此整個線程Ⅱ的操作都是在沒有同步的情況下調用 ,這說明線程Ⅰ的語句(1)和線程Ⅱ的語句(7)之間并不存在happen-before關系,這就意味著線程Ⅱ在執(zhí)行語句(7)完全有可能觀測不到線程Ⅰ在語句(1)處對someFiled寫入的值,這就是DCL的問題所在。很荒謬,是吧?DCL原本是為了逃避同步,它達到了這個目的,也正是因為如此,它最終受到懲罰,這樣的程序存在嚴重的bug,雖然這種bug被發(fā)現(xiàn)的概率絕對比中彩票的概率還要低得多,而且是轉瞬即逝,更可怕的是,即使發(fā)生了你也不會想到是DCL所引起的。

  我的理解是:線程I 和線程II 都有自己的工作存儲,線程I 創(chuàng)建好了instance后,向內存刷新的時間是不確定的,所以線程Ⅱ在執(zhí)行語句(7)完全有可能觀測不到線程Ⅰ在語句(1)處對someFiled寫入的值。

  那么由于在java 5中多增加了一條happen-before規(guī)則:

•對volatile字段的寫操作happen-before后續(xù)的對同一個字段的讀操作。

  利用這條規(guī)則我們可以將instance聲明為volatile,即: private volatile static LazySingleton instance;
  根據(jù)這條規(guī)則,我們可以得到,線程Ⅰ的語句(5) -> 語線程Ⅱ的句(2) (也就是線程),根據(jù)單線程規(guī)則,線程Ⅰ的語句(1) -> 線程Ⅰ的語句(5)和語線程Ⅱ的句(2) -> 語線程Ⅱ的句(7),再根據(jù)傳遞規(guī)則就有線程Ⅰ的語句(1) -> 語線程Ⅱ的句(7),這表示線程Ⅱ能夠觀察到線程Ⅰ在語句(1)時對someFiled的寫入值,程序能夠得到正確的行為。

  補充:在java5之前對final字段的同步語義和其它變量沒有什么區(qū)別,在java5中,final變量一旦在構造函數(shù)中設置完成(前提是在構造函數(shù)中沒有泄露this引用),其它線程必定會看到在構造函數(shù)中設置的值。而DCL的問題正好在于看到對象的成員變量的默認值,因此我們可以將LazySingleton的someField變量設置成final,這樣在java5中就能夠正確運行了。

以上內容是小編給大家介紹的Java中Volatile關鍵字的知識,希望對大家有所幫助!

相關文章

  • Java面向對象基礎詳解

    Java面向對象基礎詳解

    這篇文章主要介紹了JJava面向對象的基礎,文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-10-10
  • java8傳函數(shù)方法圖文詳解

    java8傳函數(shù)方法圖文詳解

    在本篇文章中小編給大家整理了關于java8傳函數(shù)方法和相關知識點,需要的朋友們學習下。
    2019-04-04
  • spring-boot整合Micrometer+Prometheus的詳細過程

    spring-boot整合Micrometer+Prometheus的詳細過程

    這篇文章主要介紹了springboot整合Micrometer+Prometheus的詳細過程,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-05-05
  • 基于Consumer接口、Predicate接口初使用

    基于Consumer接口、Predicate接口初使用

    這篇文章主要介紹了Consumer接口、Predicate接口初使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 一文詳解Springboot集成mybatis-plus

    一文詳解Springboot集成mybatis-plus

    這篇文章主要介紹了Mybatis-Plus與SpringBoot整合,并在項目中實戰(zhàn)運用,列舉其增刪改查的使用方式,對學習或工作有一定的幫助,需要的小伙伴可以參考閱讀
    2023-04-04
  • java留言管理系統(tǒng)中模糊查詢實例分享

    java留言管理系統(tǒng)中模糊查詢實例分享

    這篇文章主要為大家詳細介紹了基于MVC+DAO的留言管理系統(tǒng)中java模糊查詢的簡單使用方法,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Java數(shù)據(jù)結構和算法之冒泡,選擇和插入排序算法

    Java數(shù)據(jù)結構和算法之冒泡,選擇和插入排序算法

    這篇文章主要為大家介紹了Java冒泡,選擇和插入排序算法 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • MyBatis-Plus 處理邏輯刪除與查詢的5種核心實現(xiàn)方法

    MyBatis-Plus 處理邏輯刪除與查詢的5種核心實現(xiàn)方法

    本文介紹了MyBatis-Plus在Java開發(fā)中實現(xiàn)邏輯刪除的5種方法,包括全局配置、實體類注解、局部配置、查詢過濾和多租戶結合,每種方法都有其適用場景和優(yōu)缺點,開發(fā)者可以根據(jù)項目需求選擇最合適的方案,感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • JAVA Future類的使用詳解

    JAVA Future類的使用詳解

    這篇文章主要介紹了JAVA Future類的使用詳解,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下
    2021-04-04
  • Maven 配置中的 <mirror>繞過 HTTP 阻斷機制的方法

    Maven 配置中的 <mirror>繞過 HTTP 阻斷機制的方法

    這篇文章主要介紹了Maven 配置中的 <mirror>繞過 HTTP 阻斷機制的方法,本文給大家分享問題原因及解決方案,感興趣的朋友一起看看吧
    2025-06-06

最新評論

正宁县| 毕节市| 泸水县| 大城县| 澜沧| 万州区| 资中县| 岳池县| 六安市| 延长县| 寿阳县| 安顺市| 大埔区| 芦溪县| 新宁县| 鹿泉市| 阳谷县| 南雄市| 佛教| 文安县| 福海县| 大埔区| 万源市| 城口县| 封开县| 铜川市| 毕节市| 延寿县| 德令哈市| 顺昌县| 莆田市| 南皮县| 商南县| 抚宁县| 嘉荫县| 美姑县| 浦县| 泽州县| 合水县| 高密市| 锡林郭勒盟|