亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中的悲觀鎖和樂觀鎖怎么實現

發布時間:2023-04-20 11:36:49 來源:億速云 閱讀:127 作者:iii 欄目:開發技術

今天小編給大家分享一下Java中的悲觀鎖和樂觀鎖怎么實現的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

悲觀鎖(Pessimistic Locking)

悲觀鎖在并發環境中認為數據隨時會被其他線程修改,因此每次在訪問數據時都會加鎖,直到操作完成后才釋放鎖。悲觀鎖適用于寫操作多、競爭激烈的場景,比如多個線程同時對同一數據進行修改或刪除操作的情況。悲觀鎖可以保證數據的一致性,避免臟讀、幻讀等問題的發生

悲觀鎖就像一個大保安,總是認為有壞人想要偷走共享資源,于是它把資源護得緊緊的,不讓任何人接近,同時還會排隊等待資源,想要使用就得先獲取鎖,這樣雖然安全可靠,但是也會導致效率低下,因為別的線程必須等待鎖的釋放才能繼續執行。

Java中常用的悲觀鎖是synchronized關鍵字和ReentrantLock類。

使用synchronized關鍵字實現悲觀鎖的代碼如下:

synchronized (lock) {
    //訪問共享資源的代碼塊
}

使用ReentrantLock實現悲觀鎖的代碼如下:

ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
    //訪問共享資源的代碼塊
} finally {
    lock.unlock();
}

悲觀鎖存的問題:

  • 效率低:悲觀鎖需要獲取鎖才能進行操作,當有多個線程需要訪問同一份數據時,每個線程都需要先獲取鎖,然后再進行操作,如果鎖競爭激烈,就會導致線程等待鎖的釋放,浪費了大量的時間。

  • 容易引起死鎖:悲觀鎖在獲取鎖的過程中,如果獲取不到就會一直等待,如果不同的線程都在等待對方釋放鎖,就會導致死鎖的情況出現。

  • 可能會引起線程阻塞:當某個線程獲取到鎖時,其他線程需要等待,如果等待的時間過長,就會導致線程阻塞,影響應用的性能。

樂觀鎖

樂觀鎖在并發環境中認為數據一般情況下不會被其他線程修改,因此在訪問數據時不加鎖,而是在更新數據時進行檢查。如果檢查到數據被其他線程修改,則放棄當前操作,重新嘗試更新。

樂觀鎖適用于讀操作多、寫操作少的場景,比如多個線程同時對同一數據進行讀取操作的情況。樂觀鎖可以減少鎖的競爭,提高系統的并發性能。

樂觀鎖就像一個樂天派,總是認為沒有壞人想要偷走共享資源,于是它就不怎么防范,直接對資源進行操作,如果沒有其他線程對資源進行修改,操作就會成功,否則就會進行重試,這樣雖然效率高,但是如果多個線程同時進行修改,就會導致競爭和沖突,需要進行額外的處理。

Java中常用的樂觀鎖是基于CAS(Compare and Swap,比較和交換)算法實現的。

CAS操作包括三個操作數:內存地址V舊的預期值A新的值B。CAS操作首先讀取內存地址V中的值,如果該值等于舊的預期值A,那么將內存地址V中的值更新為新的值B;

否則,不進行任何操作。在更新過程中,如果有其他線程同時對該共享資源進行了修改,那么CAS操作會失敗,此時需要重試更新操作。

下面是一段基于CAS算法實現的樂觀鎖代碼:

// 假設共享資源為變量value,初始值為1
AtomicInteger value = new AtomicInteger(1);
// 假設舊的預期值為1,新的值為2
int expect = 1;
int update = 2;

// 使用CAS操作更新共享資源的值
while (true) {
    // 讀取共享資源的當前值
    int current = value.get();
    // 如果當前值等于舊的預期值,使用CAS操作將新的值更新到共享資源中
    if (current == expect) {
        if (value.compareAndSet(expect, update)) {
            // 更新成功,退出循環
            break;
        } else {
            // 更新失敗,可能是因為其他線程修改了共享資源的值,重試更新操作
            continue;
        }
    } else {
        // 當前值不等于舊的預期值,說明共享資源的值已經被其他線程修改,重試更新操作
        continue;
    }
}

在這段代碼中,內存地址V對應的是AtomicInteger對象value舊的預期值A對應的是變量expect新的值B對應的是變量update。使用AtomicInteger對象可以保證CAS操作的原子性,即只有一個線程能夠成功更新共享資源的值。使用compareAndSet方法可以判斷共享資源的值是否等于舊的預期值,并嘗試將新的值更新到共享資源中。如果更新成功,就退出循環;否則,說明共享資源的值已經被其他線程修改,需要重試更新操作。

在實際應用中,樂觀鎖的實現通常比這個簡單實現要復雜。例如,在對數據庫中的數據進行更新時,需要在更新操作中同時更新版本號和其他字段的值,并且需要處理更新失敗和重試的情況。

樂觀鎖存在的問題

CAS雖然很?效的解決原?操作,但是CAS仍然存在三?問題:ABA問題自旋時間過長只能保證單個變量的原子性

  • ABA問題:CAS算法在比較和替換時只考慮了值是否相等,而沒有考慮到值的版本信息。如果一個值在操作過程中被修改了兩次,從原值變成新值再變回原值,此時CAS會認為值沒有發生變化,從而出現操作的錯誤。為了解決ABA問題,可以在共享資源中增加版本號,每次修改操作都將版本號加1,從而保證每次更新操作的唯一性。在更新數據時先讀取當前版本號,如果與自己持有的版本號相同,則可以更新數據,否則更新失敗。版本號算法可以避免ABA問題,但需要維護版本號,增加了代碼復雜度和內存開銷。

  • 自旋時間過長:由于CAS算法在失敗時會一直自旋,等待共享變量可用,如果共享變量一直不可用,就會出現自旋時間過長的問題,浪費CPU資源。

  • 只能保證單個變量的原子性:CAS算法只能保證單個變量的原子性,如果需要多個變量的原子操作,就需要使用鎖等其他方式進行保護。

悲觀鎖和樂觀鎖的對比


悲觀鎖樂觀鎖
性能
數據一致性
實現復雜度簡單復雜
加鎖方式基于鎖機制基于版本號機制
應用場景讀少寫多讀多寫少
存在的問題效率低、容易引起死鎖、可能會引起線程阻塞ABA問題、自旋時間過長、只能保證單個變量的原子性

以上就是“Java中的悲觀鎖和樂觀鎖怎么實現”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长汀县| 海南省| 芜湖县| 吴堡县| 大方县| 清镇市| 焦作市| 辽中县| 沙雅县| 马鞍山市| 望奎县| 隆昌县| 漳平市| 攀枝花市| 阜新市| 新乡县| 桑日县| 晋州市| 曲阜市| 温泉县| 拜泉县| 宁津县| 绥阳县| 潞西市| 南投市| 喀喇沁旗| 定远县| 沭阳县| 铜鼓县| 东山县| 丹阳市| 山东省| 洪洞县| 报价| 万源市| 宜城市| 平泉县| 澜沧| 阳谷县| 合作市| 荣成市|