首頁(yè)常見(jiàn)問(wèn)題正文

請(qǐng)談?wù)凴eadWriteLock和StampedLock

更新時(shí)間:2023-03-14 來(lái)源:黑馬程序員 瀏覽量:

IT培訓(xùn)班

  ReadWriteLock和StampedLock都是Java中的鎖實(shí)現(xiàn),它們都可以用于解決多線程并發(fā)訪問(wèn)共享資源的問(wèn)題。ReadWriteLock主要是用于讀寫(xiě)分離場(chǎng)景,StampedLock則是為了更高效地支持樂(lè)觀讀模式而設(shè)計(jì)的。

  ReadWriteLock是Java中一個(gè)比較常見(jiàn)的鎖實(shí)現(xiàn),它包含一個(gè)讀鎖和一個(gè)寫(xiě)鎖。在多個(gè)線程讀取共享資源時(shí),可以同時(shí)獲取讀鎖;當(dāng)某個(gè)線程想要修改共享資源時(shí),需要獲取寫(xiě)鎖,此時(shí)其他線程將被阻塞,直到寫(xiě)鎖被釋放。

  StampedLock是JDK1.8中新添加的鎖實(shí)現(xiàn),相對(duì)于ReadWriteLock,它可以提供更高的性能。StampedLock支持三種訪問(wèn)模式:讀、寫(xiě)和樂(lè)觀讀。在讀寫(xiě)鎖的情況下,一旦有一個(gè)寫(xiě)線程,所有讀線程都需要等待,而StampedLock中的樂(lè)觀讀模式則不需要等待寫(xiě)鎖,因?yàn)樗僭O(shè)并發(fā)沖突的可能性很低。

  以下是示例代碼演示了如何使用ReadWriteLock和StampedLock實(shí)現(xiàn)線程安全的共享資源訪問(wèn):

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

public class Example {
    private int count = 0;
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private StampedLock stampedLock = new StampedLock();

    public void incrementWithReadWriteLock() {
        readWriteLock.writeLock().lock();
        try {
            count++;
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    public int getCountWithReadWriteLock() {
        readWriteLock.readLock().lock();
        try {
            return count;
        } finally {
            readWriteLock.readLock().unlock();
        }
    }

    public void incrementWithStampedLock() {
        long stamp = stampedLock.writeLock();
        try {
            count++;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
    }

    public int getCountWithStampedLock() {
        long stamp = stampedLock.tryOptimisticRead();
        int currentCount = count;
        if (!stampedLock.validate(stamp)) {
            stamp = stampedLock.readLock();
            try {
                currentCount = count;
            } finally {
                stampedLock.unlockRead(stamp);
            }
        }
        return currentCount;
    }
}

  在這個(gè)示例中,Example類(lèi)中有一個(gè)共享資源count,通過(guò)readWriteLock和stampedLock實(shí)現(xiàn)了對(duì)它的線程安全訪問(wèn)。其中incrementWithReadWriteLock和getCountWithReadWriteLock方法使用了ReadWriteLock,incrementWithStampedLock和getCountWithStampedLock方法使用了StampedLock。

  在incrementWithStampedLock和getCountWithStampedLock方法中,我們使用了StampedLock的樂(lè)觀讀模式。首先我們嘗試獲取一個(gè)樂(lè)觀讀鎖,然后讀取共享資源count的值。如果在樂(lè)觀讀的過(guò)程中沒(méi)有其他線程獲取寫(xiě)鎖修改了count,那么我們就可以直接返回樂(lè)觀讀取的值。如果在樂(lè)觀讀的過(guò)程中,有其他線程獲取了寫(xiě)鎖并修改了count,那么樂(lè)觀讀鎖就會(huì)失效,我們需要獲取一個(gè)讀鎖,并重新讀取count的值,最后釋放讀鎖并返回當(dāng)前讀取到的count值。

  需要注意的是,StampedLock的樂(lè)觀讀模式并不適用于所有場(chǎng)景。如果在樂(lè)觀讀過(guò)程中,有較高的并發(fā)寫(xiě)操作,那么會(huì)導(dǎo)致樂(lè)觀讀的效率變得低下,因?yàn)槊看螛?lè)觀讀都需要進(jìn)行一次讀鎖的獲取和釋放操作。在這種情況下,使用ReadWriteLock可能更加適合。

  總的來(lái)說(shuō),ReadWriteLock和StampedLock都是Java中非常實(shí)用的鎖實(shí)現(xiàn),可以在多線程并發(fā)訪問(wèn)共享資源的情況下保證線程安全。在實(shí)際開(kāi)發(fā)中,需要根據(jù)具體場(chǎng)景和需求來(lái)選擇合適的鎖實(shí)現(xiàn)。

1678757415555_領(lǐng)取課程.jpg

分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!