gpt4 book ai didi

Java多线程缓存的锁定策略

转载 作者:太空宇宙 更新时间:2023-11-04 10:13:57 25 4
gpt4 key购买 nike

我正在设计一个缓存,可以在其中保存安全价格,计算起来很耗时。计算完成后,我将它们存储在 map 中:安全性作为关键,价格作为值(value)。简单的解决方案是在这里使用 ConcurrentHashMap ,但我尝试使用多线程程序来理解不同的锁定策略。

这里我尝试不同的方法来锁定,以防我需要更新进程缓存中的证券价格(它可以被视为任何实体类)。

第一种方法:在这里,我尝试在缓存类中提供锁定,以便不需要客户端锁定。

第一种方式的问题:即使我需要更新一种证券的价格,我也会对所有证券进行锁定,因为 MyCache 是单例的,并且所有情况(putPrice 和 getPrice 方法调用)都使用相同的锁定实例,因此尝试更新其他证券的所有其他线程也在等待锁定,尽管这可以并行完成。

第一种方式的代码:

class Security {
int secId;
}
// Singleton class MyCache
public 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构造函数中使用Security(实例控制类)对象。 MyCache 不像第一种情况那样是单例的。客户端代码需要实例化 MyCache 的新对象,并传递 Security 对象。

第二种方式的问题:这里可能会增加复杂性,如果应该通过 Security 获取锁,为什么我们不在 Security 类中实现锁定相关代码,我们可以在那里提供 getPrice 和 updatePrice 方法,并使用关键部分来阻止同一 Security 的多个线程同时进入(实例控制类,一个 Security 只有一个对象)。

第二种方式的代码:

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;
}
}

public class MyCache {

private static final HashMap<Security, BigDecimal> cache = new HashMap();

private final Security security;

public MyCache(Security security) {
this.security = security;
}

public BigDecimal getPrice(Security security) {
synchronized(security) {
BigDecimal price = cache.get(security);
if (price == null) {
price = new BigDecimal(-9999.9999);
}
return price;
}
}

public void putPrice(Security security, BigDecimal price) {
synchronized (security){
cache.put(security, price);
}
}
}

最佳答案

我不确定您在第二个示例中要做什么,您有(1)不必要的构造函数和字段,以及(2)不必要的安全映射(没有进一步的信息,我担心这是无用的)。您的第一个解决方案是这两个解决方案中最“正确”的一个,除非您想要修改 secId (在这种情况下,您需要在 Security 类中进行额外的同步)。

我认为最理想的解决方案是在这种情况下使用 ConcurrentHashMap 并取消锁定。

关于Java多线程缓存的锁定策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51956888/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com