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

Java volatile的幾種使用場景分析

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

回答

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

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

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

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

詳解

volatile 使用條件

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

  • 寫入變量不依賴當(dāng)前值:變量的新值不能依賴于之前的舊值。如果變量的當(dāng)前值與新值之間存在依賴關(guān)系,那么僅使用 volatile 是不夠的,因?yàn)樗荒鼙WC一系列操作的原子性。比如 i++。
  • 變量不參與與其他變量的不變性條件:如果一個(gè)變量是與其他變量共同參與不變性條件的一部分,那么簡單地聲明變量為 volatile 是不夠的。

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

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

volatile 使用場景

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

狀態(tài)標(biāo)志

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

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

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

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

    private void doSomething() {
        // 實(shí)際任務(wù)邏輯
    }
}

DCL 的單例模式

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

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

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

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

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

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

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

下面是偽代碼:

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 = ...; // 被保護(hù)的數(shù)據(jù)

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

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

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

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

相關(guān)文章

最新評論

梨树县| 郁南县| 象州县| 贞丰县| 桂东县| 平遥县| 滕州市| 临朐县| 大田县| 攀枝花市| 太谷县| 巴东县| 综艺| 尼木县| 龙井市| 安丘市| 邯郸市| 鲁甸县| 泾阳县| 静宁县| 布尔津县| 明水县| 遂川县| 樟树市| 霍城县| 张掖市| 象山县| 广安市| 镇雄县| 峨眉山市| 象山县| 新邵县| 太和县| 石阡县| 乐业县| 讷河市| 望城县| 道孚县| 黄平县| 开远市| 赤水市|