- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 putIfAbsent 时遇到问题,第二个线程将在第一个线程完成使用 pk 更新值之前尝试访问该值。
示例代码。
public <T> Object getLookupValue(final Class<T> type, String key, ConcurrentHashMap<String, T> concurrentMap) {
try {
T value = concurrentMap.get(key);
if (value == null) {
System.out.println("save");
T t = type.getDeclaredConstructor(String.class).newInstance(key);
Object returnedValue = concurrentMap.putIfAbsent(key, t);
if (returnedValue == null) {
System.out.println("session save");
session.save(t);
System.out.println("t ouput " + t.toString());
return t;
}
return concurrentMap.get(key);
} else {
System.out.println("update" + concurrentMap.get(name));
return concurrentMap.get(key);
}
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException ex) {
System.out.println("getLookupValue " + ex);
Logger.getLogger(LineReaderParserImpl.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
输出
key 2008 thread 1
save
session save
key 2008 thread 0
update Year{name =2008, pk =null}
year pk null thread 0
save
session save
t ouput Year{name =2008, pk =1}
有谁知道为什么线程 1 在线程 0 完成添加 pk 之前被调用,或者为什么线程 0 在 pk 生成之前添加对象?
最佳答案
来自 ConcurrentHashMap
API:
“但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。”
在您的方法参数中声明您的 ConcurrentHashMap
final,并在同步块(synchronized block)中对其执行编辑。
public foo(final ConcurrentHashMap concurrentMap) {
synchronized (concurrentMap) {
//Your code here
}
}
这将强制每个线程在修改 concurrentMap Object
之前检索它,这将解决您的竞争条件。
另外,如果需要多个线程同时访问 map ,而只是在上面的foo()
方法中做应用代码时需要加锁,可以为该方法创建一个锁获取,而不是使用 map 本身。
final Object fooLock = new Object();
public foo(final ConcurrentHashMap concurrentMap) {
synchronized (fooLock) {
//Your code here
}
}
关于第二个例子的更多解释:
假设我有一个 ConcurrentHashMap,它的键是 String,值是 Year。不同的线程可以访问它以添加/删除值,我想在一定范围内对 Years 运行分析,同时不阻止我的程序在我的分析运行时添加/删除值。
如果锁定 ConcurrentHashMap,其他线程将无法添加/删除值,直到锁定被删除。
在第二个示例中,我为抓取方法创建了一个不同的锁,因此它不会锁定 map 本身。
ConcurrentHashMap<String, Year> concurrentMap;
final Object lock = new Object();
public void runAnalysis(final ConcurrentHashMap map) {
/*synchronized (map) {
//This will cause addValue() to lock up while the analysis is running
}*/
synchronized (lock) {
//Now we can run a long-running analysis and not block the addValue() method
//Additionally, if another thread calls runAnalysis(), it must wait to
//get our lock (when a current running analysis is completed)
//before it can start
}
}
//This method needs access to concurrentMap, so we can't lock it
public void addValue() {
concurrentMap.add("key", new Year());
}
假设这一切都在 Analyzer
类中声明。我还可以像这样声明 runAnalysis() 方法:
public synchronized void runAnalysis(ConcurrentHashMap map) {
//Do analysis logic
}
此方法不是在我们的“锁”对象上获取锁,而是在Analyzer
实例上获取锁。一种略有不同的方法,通常比创建自己的锁更常见。
请注意,如果我这样做,则在运行 runAnalysis() 时,任何其他声明为“同步”的方法都将被阻止,反之亦然。你可以用锁变得尽可能复杂,但如果你只需要 一个 方法来同步类实例,那么获取实例锁而不是单独为方法创建锁看起来更干净.
您应该查阅一些关于 Java 中的多线程、同步和锁的教程。
关于java - 多线程和 putIfAbsent 的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19674253/
是否可以使用 putIfAbsent 或其任何等效项(如短路运算符)。 myConcurrentMap.putIfAbsent(key,calculatedValue) 我希望如果已经存在计算值,则不
我正在使用 Cassandra 并使用 Datastax Java 驱动程序。我正在尝试通过缓存来重用准备好的语句。 private static final ConcurrentHashMap
我想在我的应用程序中使用 ConcurrentSkipListMap,但不太确定如何处理它。查看源代码,我没有找到任何 Lock 获取的 synchronized 语句。 Documentation也
我有这个 map 定义: TreeMap > 它可能包含数百万个条目,我还需要一个“自然顺序”(这就是我选择 TreeMap 的原因,尽管如果需要我可以编写一个比较器)。 所以,为了向 map 添加元
public static void main(String args[]) throws Exception { ConcurrentHashMap dps = new C
我在使用 putIfAbsent 时遇到问题,第二个线程将在第一个线程完成使用 pk 更新值之前尝试访问该值。 示例代码。 public Object getLookupValue(final Cl
我有一个 ConcurrentHashMap 和一个将字符串放入映射中的方法,然后我根据插入的值在同步块(synchronized block)中执行一些操作。 putIfAbsent 返回与指定键关
我想使用一个等同于 ConcurrentMap 的 map (我想要等同于 putIfAbsent 方法)但这不会强制我创建事先反对。 例如当我这样做时: m.putIfAbsent( key, ne
ConcurrentMap 指定putIfAbsent() 的返回值为: the previous value associated with the specified key, or null i
我是 Java 世界的新手,正在探索 concurrentHashMap,在探索 concurrentHashMap API 时,我发现了 putifAbsent()方法 public V putIf
我发布了一个答案 here其中演示使用 ConcurrentMap 的 putIfAbsent 方法的代码读取: ConcurrentMap map = new ConcurrentHashMap (
在his talk about Effective Java在 54:15 Joshua Bloch 建议在 putIfAbsent 之前使用 get 以提高性能和并发性。这让我想到了为什么这个优化还
查看接口(interface)Map中默认方法putIfAbsent的实现, default V putIfAbsent(K key, V value) { V v = get(key);
在 Java 中,我想向常规映射添加一个 getOrAdd 方法,就像在 ConcurrentHashMap 上添加 putIfAbsent 一样。 此外,对于某个键,我想存储一个项目列表。这是我的尝
我有一种情况,调用者希望根据当前实例(标识符)获取 bean 的对象。现在,如果当前实例存在 bean 对象,则不应再次创建它。所以有两种方法(我认为)可以做到这一点 - 1. Using putIf
我有一个 java.util.concurrent.ConcurrentHashMap,如果它不存在,我想放置它,但如果存在,我也想将其删除。像这样的东西: ConcurrentHashMap map
我有一个像这样的 ConcurrentMaps 的 ConcurrentMap... ConcurrentMap> mapsMap = new ConcurrentHashMap<>(); 现在在某些
从昨天开始,我一直在阅读并发性知识,我不太了解...但是有些事情开始变得清晰... 我理解为什么双重检查锁定不安全(我想知道这种罕见情况发生的概率是多少)但是 volatile 修复了 1.5 + 中
简介 这是关于 infinispan 缓存的,但我认为这是一个足够通用的问题。 在我的 infinispan 缓存中,我使用 putIfAbsent 方法将项目输入到缓存中,并使用 remove 方法
我在 tomcat 下部署了一个 java web 应用程序,突然 API 的响应时间变慢,如快照所示(抱歉,由于缺乏声誉,我无法发布图像。)。重启tomcat后即可恢复正常。 唯一引起我注意的可疑代
我是一名优秀的程序员,十分优秀!