欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中volatile關鍵字的作用是什么舉例詳解

 更新時間:2025年04月22日 08:38:53   作者:+720  
這篇文章主要介紹了Java中volatile關鍵字的作用是什么的相關資料,volatile關鍵字在Java中用于修飾變量,提供可見性和禁止指令重排的特性,但不保證原子性,它通過內存屏障實現(xiàn)這些特性,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

前言

volatile 是 Java 中的一個關鍵字,用于修飾變量。它提供了 可見性 和 禁止指令重排 的特性,但不保證 原子性。

1. 可見性 (Visibility)

  • 問題背景: 在多線程環(huán)境下,每個線程都有自己的工作內存(例如 CPU 緩存),線程對共享變量的讀寫操作可能不是直接在主內存中進行的,而是在工作內存中進行的。這可能導致一個線程修改了共享變量的值,而其他線程卻看不到這個修改,從而讀取到過期的值。
  • volatile 的作用: 當一個變量被 volatile 修飾時,它會保證:
    • 寫操作: 當一個線程修改了 volatile 變量的值,這個新值會立即被 刷新 到主內存中。
    • 讀操作: 當一個線程讀取 volatile 變量時,它會從主內存中讀取最新的值,而不是從自己的工作內存中讀取。
  • 實現(xiàn)原理: volatile 通過 內存屏障 (Memory Barrier) 來實現(xiàn)可見性。內存屏障是一種 CPU 指令,它可以阻止編譯器和 CPU 對指令進行重排序,并強制將工作內存中的數(shù)據(jù)刷新到主內存,或從主內存讀取數(shù)據(jù)。

代碼示例:

public class VolatileVisibilityExample {
    private static volatile boolean flag = false;
 // private static boolean flag = false; 如果不使用volatile,可能出現(xiàn)線程1無法停止的情況

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            while (!flag) {
                // ... (循環(huán)執(zhí)行某些操作) ...
            }
            System.out.println("Thread 1 stopped.");
        });

        Thread thread2 = new Thread(() -> {
            try {
                Thread.sleep(1000); // 讓 thread1 先執(zhí)行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag = true; // 修改 flag 的值
            System.out.println("Thread 2 set flag to true.");
        });

        thread1.start();
        thread2.start();
    }
}

2. 禁止指令重排 (Ordering)

  • 問題背景: 為了優(yōu)化性能,編譯器和 CPU 可能會對指令的執(zhí)行順序進行重排序(reordering),只要不影響單線程程序的執(zhí)行結果。但在多線程環(huán)境下,指令重排可能導致程序出現(xiàn)意外的行為。
  • volatile 的作用: volatile 關鍵字可以禁止特定類型的指令重排:
    • 寫后讀: 不能將 volatile 變量的寫操作重排到讀操作之后。
    • 寫后寫: 不能將 volatile 變量的寫操作重排到另一個 volatile 變量的寫操作之后。
    • 讀后讀/寫: 不能將volatile變量的讀操作重排到另一個volatile變量的讀操作或寫操作之后。
  • 實現(xiàn)原理: volatile 通過插入特定類型的內存屏障來禁止指令重排。例如,在 volatile 變量的寫操作之后會插入一個 StoreStore 屏障,在讀操作之前會插入一個 LoadLoad 屏障,以及可能的StoreLoad屏障。
  • 雙重檢查鎖定 (Double-Checked Locking) 的例子: volatile 經常用于雙重檢查鎖定模式,以防止指令重排導致的問題。
    //單例模式
    public class Singleton{
        //使用volatile禁止instance = new Singleton()的指令重排
        private static volatile Singleton instance;
    
        private Singleton(){}
    
        public static Singleton getInstance(){
            if(instance == null){ //第一次檢查
                synchronized(Singleton.class){
                    if(instance == null){ //第二次檢查,防止多個線程同時通過第一次檢查
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

3. 不保證原子性 (Atomicity)

  • 重要說明: volatile 不保證 操作的原子性。原子性指的是一個操作是不可分割的,要么全部執(zhí)行,要么不執(zhí)行,不會出現(xiàn)執(zhí)行一半的情況。
  • 例子: volatile 變量的自增操作 (i++) 不是原子性的。它實際上包含了三個步驟:讀取 i 的值、將 i 的值加 1、將新值寫回 i。在多線程環(huán)境下,這三個步驟之間可能會被其他線程打斷,導致結果錯誤。
  • **解決:**如果需要保證原子性,可以使用 synchronized、ReentrantLock 或原子類(如 AtomicInteger)。

總結:

  • volatile 關鍵字用于修飾變量,提供可見性和禁止指令重排的特性。
  • 可見性保證線程對 volatile 變量的讀寫操作都是直接在主內存中進行的。
  • 禁止指令重排防止編譯器和 CPU 對 volatile 變量相關的指令進行重排序。
  • volatile 不保證 原子性。
  • volatile 通常用于狀態(tài)標志、雙重檢查鎖定等場景。

問題分析:

這個問題考察了對 volatile 關鍵字的理解,包括它的作用、特性(可見性、禁止指令重排)以及局限性(不保證原子性)?;卮饡r需要清晰地解釋這些概念,并提供一些代碼示例來說明問題。

與其他問題的知識點聯(lián)系:

  • 什么是 Java 內存模型(JMM)? volatile 是 Java 內存模型 (JMM) 的一部分,它定義了線程和主內存之間的交互規(guī)則。
  • 什么是 Java 中的原子性、可見性和有序性? volatile 提供了可見性和有序性(禁止指令重排),但不保證原子性。
  • 什么是 Java 的 happens-before 規(guī)則? volatile 變量的寫操作 happens-before 于后續(xù)對該變量的讀操作。
  • 什么是 Java 中的指令重排? volatile 可以禁止特定類型的指令重排。
  • Java 中的 synchronized 是怎么實現(xiàn)的? synchronized 提供了原子性、可見性和有序性。在某些情況下,volatile 可以作為 synchronized 的一種輕量級替代方案(如果只需要保證可見性和有序性)。
  • 你使用過 Java 中的哪些原子類? 原子類(如 AtomicInteger)提供了原子操作,可以用來替代 volatile + 額外同步的方案。
  • Java 中的 final 關鍵字是否能保證變量的可見性? final關鍵字可以保證可見性。

理解這些聯(lián)系可以幫助你更全面地掌握 Java 并發(fā)編程的知識,并了解如何在實際應用中選擇合適的同步機制。

到此這篇關于Java中volatile關鍵字的作用是什么的文章就介紹到這了,更多相關Java volatile關鍵字的作用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Maven模版Bug及解決辦法

    Maven模版Bug及解決辦法

    默認,會幫我們創(chuàng)建src/main/resources 按照Maven的規(guī)范,Maven會有3個目錄,分別是: src/main/java : java源文件存放位置 src/main/resource : resource資源,如配置文件等 src/test/java : 測試代碼源文件存放位置
    2016-04-04
  • minio安裝部署及使用的詳細過程

    minio安裝部署及使用的詳細過程

    MinIO是一個基于Apache?License?v2.0開源協(xié)議的對象存儲服務,下面這篇文章主要給大家介紹了關于minio安裝部署及使用的詳細過程,文中通過實例代碼以及圖文介紹的非常詳細,需要的朋友可以參考下
    2022-09-09
  • 利用5分鐘快速搭建一個springboot項目的全過程

    利用5分鐘快速搭建一個springboot項目的全過程

    Spring Boot的監(jiān)控能夠使開發(fā)者更好地掌控應用程序的運行狀態(tài),下面這篇文章主要給大家介紹了關于如何利用5分鐘快速搭建一個springboot項目的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-05-05
  • eclipse輸出Hello World的實現(xiàn)方法

    eclipse輸出Hello World的實現(xiàn)方法

    這篇文章主要介紹了eclipse輸出Hello World的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • java基本教程之多線程基本概念 java多線程教程

    java基本教程之多線程基本概念 java多線程教程

    多線程是Java中不可避免的一個重要主體。下面是對“JDK中新增JUC包”之前的Java多線程內容的講解,JUC包是由Java大師Doug Lea完成并在JDK1.5版本添加到Java中的
    2014-01-01
  • Spring Boot 配置和使用多線程池的實現(xiàn)

    Spring Boot 配置和使用多線程池的實現(xiàn)

    這篇文章主要介紹了Spring Boot 配置和使用多線程池的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • 對spring task和線程池的深入研究

    對spring task和線程池的深入研究

    這篇文章主要介紹了對spring task和線程池的深入研究,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • javaCV開發(fā)詳解之收流器實現(xiàn)

    javaCV開發(fā)詳解之收流器實現(xiàn)

    這篇文章主要介紹了javaCV開發(fā)詳解之收流器實現(xiàn),對javaCV有研究的同學,可以參考下
    2021-04-04
  • SpringBoot使用Prometheus采集自定義指標數(shù)據(jù)的方法詳解

    SpringBoot使用Prometheus采集自定義指標數(shù)據(jù)的方法詳解

    隨著微服務在生產環(huán)境大規(guī)模部署和應用,隨之而來也帶來了新的問題,其中比較關鍵的就是關于微服務的運維和監(jiān)控,本文將結合微服務運維監(jiān)控中的指標監(jiān)控進行詳細的說明,需要的朋友可以參考下
    2024-07-07
  • Java?MyBatis實戰(zhàn)之QueryWrapper中and和or拼接技巧大全

    Java?MyBatis實戰(zhàn)之QueryWrapper中and和or拼接技巧大全

    在Java中QueryWrapper是MyBatis-Plus框架中的一個查詢構造器,它提供了豐富的查詢方法,其中包括and和or方法,可以用于構建復雜的查詢條件,這篇文章主要給大家介紹了關于Java?MyBatis實戰(zhàn)之QueryWrapper中and和or拼接技巧的相關資料,需要的朋友可以參考下
    2024-07-07

最新評論