我有一個ConcurrentHashMap
和一個方法,在地圖中放入一個字符串,然後我根據插入的值在一個同步塊中執行一些操作。ConcurrentHashMap putIfAbsent第一次
putIfAbsent
返回與指定鍵關聯的先前值,或者null如果沒有映射的關鍵 - 根據官方文檔
但是也有一些基於putIfAbsent
是否返回空執行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,因此同步在一個空對象?
logins.putIfAbsent(id,id)和您的同步塊語句不是原子的。這就是爲什麼有時第一次執行第二次登錄。在字符串文字上同步也不是個好主意 –
map應該是'logins'嗎? –
@MichaelEaster是的。對不起,我修改了代碼 –