gpt4 book ai didi

java - ConcurrentHashMap putIfAbsent 第一次

转载 作者:行者123 更新时间:2023-11-30 07:12:41 34 4
gpt4 key购买 nike

我有一个 ConcurrentHashMap 和一个将字符串放入映射中的方法,然后我根据插入的值在同步块(synchronized block)中执行一些操作。

putIfAbsent 返回与指定键关联的先前值,如果该键没有映射,则返回 null - 基于官方文档

根据 putIfAbsent 是否返回 null 来执行 2 个操作。

现在这就是窍门。我希望首先执行第一个操作(当 putIfAbsent 返回 null 时),并暂停所有其他线程。我的代码在 95% 的情况下都能按预期工作。

private final ConcurrentHashMap<String, String> logins = new ConcurrentHashMap<>();

public void login(String id){
String inserted=logins.putIfAbsent(id,id);

synchronized(logins.get(id)){
if(inserted==null){
System.out.println("First login");
}else{
System.out.println("Second login");
}
}
}

如果我从不同线程使用相同的字符串值调用此方法 login("some_id"); 有时(大约 5% 的时间)我会在控制台上收到此消息:

Second login
First login

我需要更改什么才能始终确保首先执行首次登录

更新:根据我的阅读,logins.get(id) 是否有可能返回 null ,从而在 null 对象上同步?

最佳答案

sometimes (around 5% of the time) I get this message on console:

您有一个竞争条件,即第一个添加的不是第一个打印的。

在这种情况下,您的主要瓶颈是使用 System.out,这是一个满足的资源,比使用 Map、并发或其他方式要昂贵很多倍。

在这种情况下,您也可以简化代码,这样您就只获得一个锁,即您无论如何都必须获得的 System.out 上的锁

// use System.out as lock so logging of actions is always in order.
private final Set<String> ids = Collections.newSetFromMap(new HashMap<>());

public void login(String id) {
synchronized (System.out) {
System.out.println(ids.add(id) ? "First login" : "Second login")l
}
}

关于java - ConcurrentHashMap putIfAbsent 第一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38944916/

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