gpt4 book ai didi

java - 迭代在线程安全的同步块(synchronized block)中检索到的列表吗?

转载 作者:行者123 更新时间:2023-11-30 08:41:27 24 4
gpt4 key购买 nike

我对在我们的一些遗留代码中看到的一种模式感到有点困惑。

Controller 使用映射作为缓存,采用线程安全的方法,但我仍然不确定它是否确实如此。我们有一个 map ,它在添加和检索期间被正确同步,但是,在同步块(synchronized block)之外有一些逻辑,可以进行一些额外的过滤。( map 本身和列表永远不会在此方法之外访问,因此并发修改不是问题; map 拥有一些稳定的参数,这些参数基本上不会改变,但经常使用)。 p>

代码类似于以下示例:

public class FooBarController { 

private final Map<String, List<FooBar>> fooBarMap =
new HashMap<String, List<FooBar>>();

public FooBar getFooBar(String key, String foo, String bar) {

List<FooBar> foobarList;

synchronized (fooBarMap) {
if (fooBarMap.get(key) == null) {
foobarList = queryDbByKey(key);
fooBarMap.put(key, foobarList);

} else {
foobarList = fooBarMap.get(key);
}
}

for(FooBar fooBar : foobarList) {
if(foo.equals(fooBar.getFoo()) && bar.equals(fooBar.getBar()))
return fooBar;
}

return null;
}

private List<FooBar> queryDbByKey(String key) {

// ... (simple Hibernate-query)
}

// ...
}

根据我对 JVM 内存模型的了解,这应该没问题,因为如果一个线程填充一个列表,另一个线程只能通过适当的同步从映射中检索它,确保列表的条目是可见的。 (将列表发生在得到它之前)

但是,我们不断看到这样的情况,其中未找到预期在 map 中的条目,并结合并发问题的典型臭名昭着的症状(例如,生产中的间歇性故障,我无法在我的开发环境中重现;不同的线程可以正确检索值等)

我想知道像这样遍历 List 的元素是否是线程安全的?

最佳答案

您提供的代码在并发方面是正确的。以下是保证:

  • 一次只有一个线程向映射添加值,因为映射对象是同步的
  • 线程添加的值对于所有其他进入同步块(synchronized block)的线程都是可见的

鉴于此,您可以确定迭代列表的所有线程都看到相同的元素。您描述的问题确实很奇怪,但我怀疑它们与您提供的代码有关。

关于java - 迭代在线程安全的同步块(synchronized block)中检索到的列表吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35083000/

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