gpt4 book ai didi

java - 何时以及如何使用额外的 ConcurrentHashMap 同步?

转载 作者:搜寻专家 更新时间:2023-11-01 03:33:59 25 4
gpt4 key购买 nike

在使用 ConcurrentHashMap 时,我需要知道什么时候应该在我的代码中添加一些同步块(synchronized block)。假设我有一个方法:

private static final ConcurrentMap<String, MyObjectWrapper> myObjectsCache = new ConcurrentHashMap<>(CACHE_INITIAL_CAPACITY);

public List<MyObject> aMethod(List<String> ids, boolean b) {
List<MyObject> result = new ArrayList<>(ids.size());
for (String id : ids) {
if (id == null) {
continue;
}
MyObjectWrapper myObjectWrapper = myObjectsCache.get(id);
if (myObjectWrapper == null) {
continue;
}
if (myObjectWrapper.getObject() instanceof MyObjectSub) {
((MyObjectSub) myObjectWrapper.getObject()).clearAField();
myObjectWrapper.getObject().setTime(System.currentTimeMillis());
}
result.add(myObjectWrapper.getObject());
if (b) {
final MyObject obj = new MyObject(myObjectWrapper.getObject());
addObjectToDb(obj);
}
}
return result;
}

我应该如何有效地使这个方法并发?我认为“get”是安全的,但是一旦我从缓存中获取值并更新缓存对象的字段 - 可能会出现问题,因为另一个线程可以获得相同的包装器并尝试更新相同的底层对象......我应该添加同步?如果是这样,那么我应该从“get”同步到循环迭代结束还是整个循环?

当需要对循环内的映射键/值等执行更多操作时,也许有人可以分享一些更具体的正确和有效使用 ConcurrentHashMap 的指南......

我将不胜感激。

编辑:这个问题的一些背景:我目前正在重构生产代码中的一些 dao 类,其中一些类使用 HashMaps 来缓存从数据库中检索的数据。所有使用缓存(用于写入或读取)的方法都将其全部内容放在同步(缓存) block 中(安全吗?)。我对并发没有太多经验,我很想利用这个机会学习。我天真地将 HashMaps 更改为 ConcurrentHashMaps,现在想删除需要的同步块(synchronized block)。所有缓存都用于写入和读取。所提供的方法基于我已经更改的方法之一,现在我正在尝试了解何时同步以及同步到什么程度。方法 clearAField 只是更改包装的 POJO 对象的字段之一的值,addObjectToDb 尝试将对象添加到数据库。

另一个例子是重新填充缓存:

public void findAll() throws SQLException{
// get data from database into a list
List<Data> data=getAllDataFromDatabase();
cacheCHM.clear();
cacheCHM.putAll(data);
}

在这种情况下,我应该将 clear 和 putAll 放在一个 synchronize(cacheCHM) block 中,对吗?

我试图找到并阅读一些关于正确有效地使用 CHM 的帖子/文章,但大多数都是处理单一操作,没有循环等......我发现的最好的是: http://www.javamadesoeasy.com/2015/04/concurrenthashmap-in-java.html

最佳答案

您没有提到您希望在您的应用程序中发生什么并发性,所以我假设您有多个线程调用 aMethod没有别的

您只需调用一次 ConcurrentHashMap:myObjectsCache.get(id),这很好。事实上,由于没有任何东西将数据写入您的 objectCache [参见上面的假设],您甚至不需要 ConcurrentHashMap!您可以使用任何不可变的集合。你在末尾有一行可疑的代码:addObjectToDb(obj),这个方法是否也会影响你的缓存?如果是这样,它仍然是安全的(可能,我们必须查看方法才能确定),但您肯定需要 ConcurentHashMap。

危险在于你改变对象的地方,在这里:

myObjectWrapper.getObject().clearAField();
myObjectWrapper.getObject().setTime(System.currentTimeMillis());

多个线程可以同时在同一个对象上调用这些方法。在不知道这些方法的作用的情况下,我们不能说这是否安全。如果这些方法都标记为同步,或者如果您注意确保这些方法同时运行是安全的,那么您就没问题(但请注意,这些方法的运行顺序可能与您的直觉预期不同! ).如果您不那么小心,则可能会损坏数据。

关于java - 何时以及如何使用额外的 ConcurrentHashMap 同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37730484/

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