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

Java volatile的幾種使用場景分析

 更新時間:2024年03月27日 09:24:05   作者:大明哥_  
volatile 是一種輕量級的同步機制,它能保證共享變量的可見性,同時禁止重排序保證了操作的有序性,但是它無法保證原子性,本文給大家總結了Java olatile的使用場景有哪些,并通過代碼示例講解的非常詳細,需要的朋友可以參考下

回答

volatile 是一種輕量級的同步機制,它能保證共享變量的可見性,同時禁止重排序保證了操作的有序性,但是它無法保證原子性。所以使用 volatile 必須要滿足這兩個條件:

  • 寫入變量不依賴當前值。
  • 變量不參與與其他變量的不變性條件。

volatile 比較適合多個線程讀,一個線程寫的場合,典型的場景有如下幾個:

  • 狀態(tài)標志
  • 重檢查鎖定的單例模式
  • 開銷較低的“讀-寫鎖”策略

詳解

volatile 使用條件

要想正確安全地使用 volatile ,必須要具備這兩個條件:

  • 寫入變量不依賴當前值:變量的新值不能依賴于之前的舊值。如果變量的當前值與新值之間存在依賴關系,那么僅使用 volatile 是不夠的,因為它不能保證一系列操作的原子性。比如 i++。
  • 變量不參與與其他變量的不變性條件:如果一個變量是與其他變量共同參與不變性條件的一部分,那么簡單地聲明變量為 volatile 是不夠的。

第一個條件很好理解,第二個條件這里需要解釋下。

“變量不參與與其他變量的不變性條件”,這里的“不變性條件”指的是一個或多個變量在程序執(zhí)行過程中需要保持的條件或關系,以確保程序的正確性。假設我們有兩個變量,它們需要滿足某種關系(例如,a + b = 99)。我們需要在多線程環(huán)境下保證這種關閉在任何時候都是成立的。如果這個時候我們只是將其中一個變量聲明為 volatile,雖然確保了這個變量的更新對其他線程立即可見,但卻不能保證這兩個變量作為一個整體滿足特定的不變性條件。在更新這兩個變量的過程中,其他線程可能會看到這些變量處于不一致的狀態(tài)。在這種情況下我們就需要使用鎖或者其他同步機制來保證這種關系的整體一致性。

volatile 使用場景

volatile 比較適合多個線程讀,一個線程寫的場合。

狀態(tài)標志

當我們需要用一個變量來作為狀態(tài)標志,控制線程的執(zhí)行流程時,使用 volatile 可以確保當一個線程修改了這個標志時,其他線程能夠立即看到最新的值。

public class TaskRunner implements Runnable {
    private volatile boolean running = true;  // 狀態(tài)標志,控制任務是否繼續(xù)執(zhí)行

    public void run() {
        while (running) {  // 檢查狀態(tài)標志
            // 執(zhí)行任務
            doSomething();
        }
    }

    public void stop() {
        running = false;  // 修改狀態(tài)標志,使得線程能夠停止執(zhí)行
    }

    private void doSomething() {
        // 實際任務邏輯
    }
}

DCL 的單例模式

在實現(xiàn)單例模式時,為了保證線程安全,通常使用雙重檢查鎖定(Double-Checked Locking)模式。在這種模式中,volatile 用于避免單例實例的初始化過程中的指令重排序,確保其他線程看到一個完全初始化的單例對象,具體來說,就是使用 volatile防止了Java 對象在實例化過程中的指令重排,確保在對象的構造函數(shù)執(zhí)行完畢之前,不會將 instance 的內存分配操作指令重排到構造函數(shù)之外。

public class Singleton {
    // 使用 volatile 保證實例的可見性和有序性
    private static volatile Singleton instance;

    private Singleton() {
    }
    
    public static Singleton getInstance() {
        if (instance == null) {  // 第一次檢查,避免不必要的同步
            synchronized (Singleton.class) {  // 鎖定
                if (instance == null) {  // 第二次檢查,確保只創(chuàng)建一次實例
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

開銷較低的“讀-寫鎖”策略

這種策略一般都是允許多個線程同時讀取一個資源,但只允許一個線程寫入的同步機制。這種“讀-寫鎖”非常適合讀多寫少的場景,我們可以利用 volatile + 鎖的機制減少公共代碼路徑的開銷。如下:

public class VolatileTest {  
    private volatile int value;  
    
    //讀,不加鎖,提供效率 
    public int getValue() {   
        return value;   
    }   
    //寫操作,使用鎖,保證線程安全  
    public synchronized int increment() {  
        return value++;  
    }  
}

在 J.U.C 中,有一個采用“讀-寫鎖”方式的類:ReentrantReadWriteLock,它包含兩個鎖:一個是讀鎖,另一個是寫鎖。

下面是偽代碼:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class DataStructure {
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private final Object data = ...; // 被保護的數(shù)據(jù)

    public void read() {
        readWriteLock.readLock().lock(); // 獲取讀鎖
        try {
            // 執(zhí)行讀操作
            // 例如,讀取data的內容
        } finally {
            readWriteLock.readLock().unlock(); // 釋放讀鎖
        }
    }

    public void write(Object newData) {
        readWriteLock.writeLock().lock(); // 獲取寫鎖
        try {
            // 執(zhí)行寫操作
            // 例如,修改data的內容
        } finally {
            readWriteLock.writeLock().unlock(); // 釋放寫鎖
        }
    }
}
  • 讀操作 :多個線程可以同時持有讀鎖,因此多個線程可以同時執(zhí)行 read() 方法。
  • 寫操作: 只有一個線程可以持有寫鎖,并且在持有寫鎖時,其他線程不能讀取或寫入。

這種“讀-寫鎖”策略提高了在多線程環(huán)境下對共享資源的讀取效率,尤其是在讀操作遠遠多于寫操作的情況下。但是,它也會讓我們的程序變更更加復雜,比如潛在的讀寫鎖沖突、鎖升級(從讀鎖升級到寫鎖)等問題。因此,在實際應用中,大明哥推薦直接使用 ReentrantReadWriteLock 即可,無需頭鐵自己造輪子。

以上就是Java volatile的幾種使用場景分析的詳細內容,更多關于Java volatile使用場景的資料請關注腳本之家其它相關文章!

相關文章

  • springboot前端傳參date類型后臺處理的方式

    springboot前端傳參date類型后臺處理的方式

    這篇文章主要介紹了springboot前端傳參date類型后臺處理的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 用Java驗證pdf文件的電子章簽名

    用Java驗證pdf文件的電子章簽名

    這篇文章主要介紹了如何用Java驗證pdf文件的電子章簽名,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • java.util.Collections類—emptyList()方法的使用

    java.util.Collections類—emptyList()方法的使用

    這篇文章主要介紹了java.util.Collections類—emptyList()方法的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 做java這么久了居然還不知道JSON的使用(一文帶你了解)

    做java這么久了居然還不知道JSON的使用(一文帶你了解)

    這篇文章主要介紹了做java這么久了居然還不知道JSON的使用(一文帶你了解),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • springboot如何開啟緩存@EnableCaching(使用redis)

    springboot如何開啟緩存@EnableCaching(使用redis)

    在Spring Boot項目中集成Redis主要包括添加依賴到pom.xml、配置application.yml中的Redis連接參數(shù)、編寫配置類、在啟動類上添加@EnableCaching注解以及測試接口的查詢和緩存驗證等步驟,首先,需要在pom.xml中添加spring-boot-starter-data-redis依賴
    2024-11-11
  • 詳解Java如何優(yōu)雅的實現(xiàn)字典翻譯

    詳解Java如何優(yōu)雅的實現(xiàn)字典翻譯

    當我們在Java應用程序中需要對字典屬性進行轉換返回給前端時,如何簡單、方便、并且優(yōu)雅的處理是一個重要問題。在本文中,我們將介紹如何使用Java中的序列化機制來優(yōu)雅地實現(xiàn)字典值的翻譯,從而簡化開發(fā)
    2023-04-04
  • 基于Java中UDP的廣播形式(實例講解)

    基于Java中UDP的廣播形式(實例講解)

    下面小編就為大家分享一篇基于Java中UDP的廣播形式(實例講解),具有很好的參考價值,希望對大家有所幫助
    2017-12-12
  • java數(shù)據(jù)結構與算法之希爾排序詳解

    java數(shù)據(jù)結構與算法之希爾排序詳解

    這篇文章主要介紹了java數(shù)據(jù)結構與算法之希爾排序,結合實例形式分析了希爾排序的概念、原理、實現(xiàn)方法與相關注意事項,需要的朋友可以參考下
    2017-05-05
  • IDEA中application.properties的圖標顯示不正常的問題及解決方法

    IDEA中application.properties的圖標顯示不正常的問題及解決方法

    這篇文章主要介紹了IDEA中application.properties的圖標顯示不正常的問題及解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • java.text.DecimalFormat類十進制格式化

    java.text.DecimalFormat類十進制格式化

    這篇文章主要為大家詳細介紹了java.text.DecimalFormat類十進制格式化的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03

最新評論