나는 ConcurrentHashMap
과 그 맵에 String을 넣는 메소드를 가지고있다. 그런 다음 삽입 된 값을 기반으로 동기화 된 블록에서 몇 가지 작업을 수행한다. 키의 매핑이없는 경우ConcurrentHashMap putIfAbsent 初めて
putIfAbsent
지정된 키에 관련 지을 수 있었던 이전의 값을 돌려줍니다 - 공식 문서에 따라이
putIfAbsent
반환 널 (null) 여부에 따라 실행되는이 개 조치는있다 아닙니다.
이제 여기에 속임수입니다. 첫 번째 작업 (putIfAbsent
이 null을 반환하는 경우)이 먼저 실행되고 다른 모든 스레드가 보류되도록하려고합니다. 내 코드는 의도 한대로 작동합니다. 가끔 다른 스레드 login("some_id");
에서 같은 문자열 값이 메소드를 호출하면
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");
}
}
}
은 (시간의 5 %의 주위에) 나는 콘솔에서이 메시지 : 내가 변경해야 할 무엇
Second login
First login
항상 First login
이 먼저 실행되도록 하시겠습니까?
업데이트 : 내가 읽은 바에 따르면 logins.get (id)가 null을 반환하므로 null 객체에서 동기화 할 수 있습니까?
logins.putIfAbsent (id, id) 및 동기화 된 블록 명령문은 절대 아님. 그래서 두 번째 로그인이 먼저 실행되는 경우가 있습니다.또한 문자열 리터럴을 동기화하는 것은 좋지 않습니다. –
'map'을'logins'해야합니까? –
@MichaelEaster 예. 죄송합니다. 코드를 수정했습니다. –