在并發編程中,讀寫鎖 ReentrantReadWriteLock 的性能已經算是比較高的了,因為它將悲觀鎖的粒度分的更細,在它里面有讀鎖和寫鎖,當所有操作為讀操作時,并發線程是可以共享讀鎖同時運行的,這樣就無需排隊執行了,所以執行效率也就更高。
那么問題來了,有沒有比讀寫鎖 ReentrantReadWriteLock 性能更高的鎖呢?
答案是有的,在 Java 中,比 ReentrantReadWriteLock 性能更高的鎖有以下兩種:
樂觀鎖在 Java 中最常見的實現就是 atomic 家族下的類,例如 AtomicInteger、AtomicLong 等,它的核心方法中使用了 CAS 對比并替換進行變量的修改操作,如下源碼所示:
public final int incrementAndGet() { return U.getAndAddInt(this, VALUE, 1) + 1;}public final int getAndAddInt(Object o, long offset, int delta) { int v; do { v = getIntVolatile(o, offset); } while (!weakCompareAndSetInt(o, offset, v, v + delta)); // CAS 方法 return v;}
然而,如果是高并發環境下,那么樂觀鎖可以需要通過多次自旋才能成功修改變量的數據,這種場景下,樂觀鎖的性能可能就不如 ReentrantReadWriteLock 了。
StampedLock 有三種讀寫方法:
其中 readLock() 和 writeLock() 方法與 ReentrantReadWriteLock 的用法類似,而 tryOptimisticRead() 方法則是 StampedLock 引入的新方法,它用于非常短的讀操作。
因此,我們在加鎖時,可以使用性能更高的讀樂觀鎖來替代傳統的讀鎖,如果能加鎖成功,則它可以和其他線程(即使是寫操作)一起執行,也無需排隊運行(傳統讀鎖遇到寫鎖時需要排隊執行),這樣的話 StampedLock 的執行效率就會更高,它是使用如下:
// 創建 StampedLock 實例StampedLock lock = new StampedLock();// 獲取樂觀讀鎖long stamp = lock.tryOptimisticRead(); // 讀取共享變量if (!lock.validate(stamp)) { // 檢查樂觀讀鎖是否有效 stamp = lock.readLock(); // 如果樂觀讀鎖無效,則獲取悲觀讀鎖 try { // 重新讀取共享變量 } finally { lock.unlockRead(stamp); // 釋放悲觀讀鎖 }}// 獲取悲觀讀鎖long stamp = lock.readLock(); try { // 讀取共享變量} finally { lock.unlockRead(stamp); // 釋放悲觀讀鎖}// 獲取寫鎖long stamp = lock.writeLock(); try { // 寫入共享變量} finally { lock.unlockWrite(stamp); // 釋放寫鎖}
使用樂觀讀鎖的特性可以提高讀操作的并發性能,適用于讀多寫少的場景。如果樂觀讀鎖獲取后,在讀取共享變量前發生了寫入操作,則 validate 方法會返回 false,此時需要轉換為悲觀讀鎖或寫鎖重新訪問共享變量。
本文鏈接:http://www.www897cc.com/showinfo-26-88329-0.html什么鎖比讀寫鎖性能更高?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 這一次,徹底搞懵 CRDT
下一篇: YOLOv8 中的損失函數解析