【发布时间】:2016-08-14 17:46:37
【问题描述】:
我有一个ConcurrentHashMap 和一个将字符串放入映射中的方法,然后我根据插入的值在同步块中执行一些操作。
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
我需要进行哪些更改才能始终确保首先执行First login?
更新:根据我的阅读,logins.get(id) 是否有可能返回 null ,因此在 null 对象上进行同步?
【问题讨论】:
-
logins.putIfAbsent(id,id) ,并且您的同步块语句不是原子的。这就是为什么有时会先执行第二次登录。此外,在字符串文字上同步也不是一个好主意
-
应该
map是logins吗? -
@MichaelEaster 是的。抱歉我修改了代码
标签: java java.util.concurrent concurrenthashmap concurrent-programming