문제

다음 관용구가있는 레거시 코드를보고 있습니다.

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (myMap) {
    item = myMap.get(myKey);
}

Intelli-J의 코드 검사에서 얻은 경고는 다음과 같습니다.

Synchronization on local variable 'myMap'

이것이 적절한 동기화입니까?

Map<String, Boolean> myMap = someGlobalInstance.getMap();
synchronized (someGlobalInstance.getMap()) {
    item = myMap.get(myKey);
}
도움이 되었습니까?

해결책

이것이 문제로 표시되는 이유는 로컬 변수의 동기화가 일반적으로 나쁜 생각이기 때문입니다.

만약에 물체가 반환되었습니다 someGlobalInstance.getMap() 항상 동일합니다. 그런 다음 동기화 된 블록은 실제로 준 글로벌 객체 모니터를 사용하고 코드는 예상 결과를 생성합니다.

또한 동기화 된 래퍼를 사용하라는 제안에 동의합니다. get()/put() 호출 및 더 큰 동기화 된 블록이 없습니다. 그러나지도가 있는지 확인하십시오 래퍼를 통해 액세스하거나 버그에 대한 또 다른 기회가 있습니다.

또한 someGlobalInstance.getMap() 하다 ~ 아니다 동일한 객체를 항상 반환하면 두 번째 코드 예제조차 제대로 작동하지 않으며 호출하는 것과 다른 객체와 동기화 할 수 있기 때문에 원래 코드보다 더 나빠질 수 있습니다. get() 에.

다른 팁

getMap () 메소드가하는 일에 따라 코드가 소리가 될 수 있다고 생각합니다. 스레드간에 공유 해야하는 인스턴스에 대한 참조를 유지하면 의미가 있습니다. 로컬 변수가 로컬로 초기화되지 않으므로 경고는 관련이 없습니다.

사용하는 것이 더 좋을 것이라고 생각합니다 동기화 된 래퍼 지도를 위해

알렉스는 호출하여 동기화 된 래퍼를 추가하는 것이 맞습니다. Collections.synchronizedMap(Map) 여기서 전형적인 접근법입니다. 그러나이 접근 방식을 취하면 여전히 동기화 해야하는 상황이있을 수 있습니다. Map의 자물쇠; 예를 들어지도를 반복 할 때.

Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());

// Synchronized on map to prevent ConcurrentModificationException whilst iterating.
synchronized (syncMap) {
  for (Map.Entry<String, String> entry : syncMap.entrySet()) {
    // Do work
  }
}

예를 들어, 아이디어로부터의 경고는 로컬 변수가 분명히 분명히 무시할 수 있습니다. map 다른 곳에서 검색됩니다 (someGlobalInstance) 방법 내에서 생성되기보다는 다른 스레드에서 잠재적으로 액세스 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top