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