第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會有你想問的

緩存的 Java 多線程鎖定策略

緩存的 Java 多線程鎖定策略

溫溫醬 2021-08-04 17:10:23
我正在設(shè)計(jì)一個(gè)緩存,我可以在其中保存安全價(jià)格,這些價(jià)格計(jì)算起來很耗時(shí)。計(jì)算完成后,我將它們存儲在地圖中:安全性作為關(guān)鍵,價(jià)格作為價(jià)值。簡單的解決方案是在ConcurrentHashMap這里使用,但我正在嘗試使用多線程程序來理解不同的鎖定策略。在這里,我正在嘗試不同的方法來獲取鎖定,以防我需要更新進(jìn)程緩存中的證券價(jià)格(它可以被視為任何實(shí)體類)。第一種方式:在這里,我試圖在我的緩存類中提供鎖定,以便不需要客戶端鎖定。第一種方式的問題:即使我需要更新一種證券的價(jià)格,我MyCache也會鎖定所有證券,因?yàn)槭菃卫?,并且所有情況(putPrice 和 getPrice 方法調(diào)用)都使用相同的鎖實(shí)例,因此所有其他正在嘗試的線程更新其他證券也在等待鎖定,盡管這可以并行完成。第一種方式的代碼:class Security {    int secId;}// Singleton class MyCachepublic class MyCache {    private static final HashMap<Security, BigDecimal> cache = new HashMap();    private final static ReadWriteLock lock = new ReentrantReadWriteLock();    public BigDecimal getPrice(Security security) {        lock.readLock().lock();        try {            BigDecimal price = cache.get(security);            if (price == null) {                price = new BigDecimal(-9999.9999);            }            return price;        } finally {            lock.readLock().unlock();        }    }    public void putPrice(Security security, BigDecimal price) {        lock.writeLock().lock();        try{            cache.put(security, price);        }finally {            lock.writeLock().unlock();        }    }}第二種方式:在這里,我試圖獲取對安全性的鎖定,為此我在MyCache構(gòu)造函數(shù)中使用了 Security(Instance Controlled class) 對象。MyCache不像第一種情況那樣是單身??蛻舳舜a需要實(shí)例化 MyCache 的新對象,傳遞 Security 對象。第二種方式的問題:這里可能我增加了復(fù)雜性,如果應(yīng)該通過 Security 獲取鎖為什么我們不在 Security 類中實(shí)現(xiàn)與鎖定相關(guān)的代碼,我們可以在那里提供 getPrice 和 updatePrice 方法并使用關(guān)鍵部分來阻止多個(gè)線程進(jìn)入相同相同安全的時(shí)間(實(shí)例控制類,一個(gè)安全只有一個(gè)對象)。第二種方式的代碼:class Security {    private int secId;    private final static HashMap<Integer, Security> map = new HashMap<>();    private Security(Integer secId) {        this.secId = secId;    }    public static synchronized Security getSecurity(Integer secId) {        Security security = map.get(secId);        if (security == null) {            security = new Security(secId);            map.put(secId, security);        }        return security;    }}
查看完整描述

2 回答

?
湖上湖

TA貢獻(xiàn)2003條經(jīng)驗(yàn) 獲得超2個(gè)贊

我不確定您在第二個(gè)示例中要做什么,您有 (1) 一個(gè)不必要的構(gòu)造函數(shù)和字段,以及 (2) 一個(gè)不必要的安全映射(沒有更多信息,我擔(dān)心這是無用的)。您的第一個(gè)解決方案是兩者中最“正確”的,除非您想修改secId(在這種情況下,您需要在Security類中進(jìn)行額外的同步)。

我認(rèn)為最理想的解決方案是ConcurrentHashMap在這種情況下使用并取消鎖定。


查看完整回答
反對 回復(fù) 2021-08-04
?
蠱毒傳說

TA貢獻(xiàn)1895條經(jīng)驗(yàn) 獲得超3個(gè)贊

您遇到了簡單并發(fā)結(jié)構(gòu)的問題,即更新結(jié)構(gòu)需要您鎖定整個(gè)結(jié)構(gòu),無論使用的是什么密鑰。這顯然會損害并發(fā)性。您的緩存必須可供所有線程訪問,因此鎖定它會阻止所有其他嘗試訪問該結(jié)構(gòu)的線程。

這樣做的原因是添加或刪除條目會導(dǎo)致映射中的內(nèi)部結(jié)構(gòu)被修改,從而影響其他鍵。所以你必須鎖定整個(gè)結(jié)構(gòu)。

您的第一個(gè)解決方案將起作用,但與將地圖包裝在 a 中SynchronizedMap(可能更糟)相同。

您的第二個(gè)解決方案有很多錯(cuò)誤,但通常它不會起作用,因?yàn)樗粫i定地圖。

有兩種前進(jìn)方式:

  1. 如果您事先知道所有證券是什么,您可以預(yù)先構(gòu)建包含所有已知密鑰的緩存。我相信您然后可以獲取和放置并且您不需要同步,因?yàn)槟粫采w現(xiàn)有的地圖條目。如果您真的想確定,您可以在地圖中創(chuàng)建一個(gè) Price 類作為價(jià)值項(xiàng)目,其中包含您可以修改的價(jià)格,然后使用 Price 對象預(yù)加載緩存,然后修改 Price 對象中的價(jià)格字段。您將永遠(yuǎn)不必在初始加載后執(zhí)行 get 和 put 操作。

  2. 如果您事先不知道所有鍵或者不想預(yù)加載緩存,請使用ConcurrentHashMapConcurrentHashMap確實(shí)同步,但它在內(nèi)部創(chuàng)建了多個(gè)段,并有巧妙的策略來分割一組鍵,這樣它就不必鎖定整個(gè)地圖,只需要鎖定一個(gè)段。這意味著很有可能避免緩存中的爭用。手動(dòng)條目指出讀取通常不會阻塞,并且可以向構(gòu)造函數(shù)指定并發(fā)值以控制預(yù)期的并發(fā)線程數(shù)。


查看完整回答
反對 回復(fù) 2021-08-04
  • 2 回答
  • 0 關(guān)注
  • 206 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號