W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
大家好,我是 V 哥。商城系統(tǒng)中,用戶在瀏覽商品詳情頁時可以查看庫存數(shù)量,這是讀操作,頻率較高。當用戶下單成功時,系統(tǒng)會更新庫存數(shù)量,這是寫操作,但相對較少。這是一個再常見不過的應(yīng)用場景了,在這種場景下,讀寫鎖分離設(shè)計模式就是最好的武器。
讀寫鎖分離設(shè)計模式
是一種多線程設(shè)計模式,適合在有讀多寫少的場景中使用。它通過讀寫操作的分離,提升了系統(tǒng)的并發(fā)性和性能。在這個模式中,讀操作是共享的,可以同時被多個線程執(zhí)行,而寫操作需要獨占鎖,避免并發(fā)寫入帶來的數(shù)據(jù)不一致問題。
咱們再來把讀寫鎖分離的原理先明確一下:
咱們就拿在電商平臺的商品庫存管理系統(tǒng)來說,庫存數(shù)據(jù)需要滿足如下業(yè)務(wù)需求:
回到功能業(yè)務(wù),通常要實現(xiàn)的具體功能場景是這樣的:
有了這樣的場景,采用讀寫鎖分離設(shè)計模式來優(yōu)化庫存管理,可以達到以下目標:
下面咱們來具體看一下案例實現(xiàn),我們要實現(xiàn)一個商品庫存管理,需求是這樣滴:
InventoryManager
,使用 ReentrantReadWriteLock
進行讀寫鎖分離。checkStock
方法進行庫存讀取操作,獲取讀鎖。updateStock
方法進行庫存更新操作,獲取寫鎖。以下是實現(xiàn)代碼:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class InventoryManager {
// 商品庫存存儲
private final Map<String, Integer> inventory = new HashMap<>();
// 讀寫鎖
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
// 獲取庫存數(shù)量(讀操作)
public int checkStock(String productId) {
readLock.lock();
try {
return inventory.getOrDefault(productId, 0);
} finally {
readLock.unlock();
}
}
// 更新庫存數(shù)量(寫操作)
public void updateStock(String productId, int quantity) {
writeLock.lock();
try {
int currentStock = inventory.getOrDefault(productId, 0);
inventory.put(productId, currentStock + quantity);
System.out.println("Updated stock for product " + productId + ": " + (currentStock + quantity));
} finally {
writeLock.unlock();
}
}
}
在測試案例中,模擬多個用戶并發(fā)訪問庫存,讀取庫存的線程可以并發(fā)執(zhí)行,而更新庫存的線程會獨占鎖。
public class InventoryManagerTest {
public static void main(String[] args) {
InventoryManager inventoryManager = new InventoryManager();
// 初始化庫存
inventoryManager.updateStock("product_1", 100);
// 模擬多個線程同時讀取庫存
for (int i = 0; i < 5; i++) {
new Thread(() -> {
System.out.println("Stock for product_1: " + inventoryManager.checkStock("product_1"));
}).start();
}
// 模擬一個線程更新庫存
new Thread(() -> {
inventoryManager.updateStock("product_1", -10);
System.out.println("Stock after selling 10 units for product_1: " + inventoryManager.checkStock("product_1"));
}).start();
}
}
checkStock
):
readLock
加鎖,只需獲取讀鎖,不會影響其他讀取線程。checkStock
方法,提升讀取并發(fā)性。updateStock
):
writeLock
加鎖,寫操作會阻塞其他讀寫操作。輸出可能如下(順序可能有所不同):
Stock for product_1: 100
Stock for product_1: 100
Stock for product_1: 100
Stock for product_1: 100
Stock for product_1: 100
Updated stock for product product_1: 90
Stock after selling 10 units for product_1: 90
寫安全
重要程度來看,犧牲點性能是完全可以忍受的。到這里,你是不是可以感受到讀寫鎖分離設(shè)計模式解決了大問題了呢,并發(fā)場景下我們必須要考慮這個問題。你學(xué)沸了嗎,關(guān)注威哥愛編程,一起搞不寂寞。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: