문제

Collections.synchronizedMap ()과 모든 메소드가 동기화 된 해시 맵 주변의 래퍼의 차이점은 무엇입니까? Collection.synchronizedMap ()는 내부적으로 모든 방법에 대해 동일한 잠금을 유지합니다.

기본적으로 다음 코드 스 니펫의 차이점은 무엇입니까?

Class C {    
    Object o;

    public void foo() {
       synchronized(o) {
           // thread safe code here
       }
    }
}

그리고

Class C {
    Object o;

    public synchronized void foo() {

    }
}
도움이 되었습니까?

해결책

한 가지 차이점 만 있습니다.

collections.synchronizedmap 가능합니다 자체와 다른 모니터를 사용합니다.

동기화 된 방법을 사용하는 것은 사용과 동일합니다 sychnchonized(this)-블록은 래퍼가 모니터이며 래퍼 외부에서 잠글 수 있음을 의미합니다.

외부 응용 프로그램이 모니터를 잠그고 싶지 않은 경우 숨겨져 있어야합니다.

다른 한편으로, 스레드 안전 방식으로 여러 메소드를 호출하려면 전체 컬렉션을 잠그는 가장 쉬운 방법입니다 (실제로는 매우 확장 가능하지는 않습니다).

추신 : 재사용의 경우, 래퍼를 변경하지 않고 나중에 다른 맵 구현으로 전환 할 수 있기 때문에 클래스를 무시하는 것보다 메소드 호출을 백업 맵으로 위임하는 것이 좋습니다.

다른 팁

두 접근 방식 모두 객체에 대한 모니터를 얻으므로 정확히 동일하게 수행해야합니다. 차이의 주된 이유는 건축입니다. 동기화 된 래퍼를 사용하면 기본 비 스레드 안전 변동을 쉽게 확장 할 수 있습니다.

어느 쪽도 사용하지 않는다고 말하면 Concurrenthashmap을 사용하십시오. 잠금 스트립을 사용하므로 오버 헤드 + 경합 측면에서 동일하기 때문에 두 가지 접근 방식보다 훨씬 빠릅니다. 잠금 스트립을 사용하면 백업 배열의 세그먼트를 독립적으로 잠글 수 있습니다. 즉, 두 스레드가 동일한 잠금을 취득하도록 요청할 가능성이 적습니다.

휠을 재발 명하지 말고 API가 제공하는 것을 사용하십시오.

당신은 항상 모든 것을 뭉치지 않고 항상 장식해야합니다.

항상 일반지도를 가져 와서 컬렉션으로 장식하거나 java.util.concurrent를 사용하고 실제 잠금 장치를 사용하여 맵을 원자 적으로 검사하고 업데이트 할 수 있습니다. 내일 당신은 해시 가능을 트리 맵으로 바꾸고 싶을 것입니다. 그리고 당신은 당신이 해시 테이블에 붙어 있으면 곤경에 처할 것입니다.

그렇다면 왜 물어봐? :) 클래스가 java.util 패키지에 배치되면 약간의 마법이 발생하고 Java 코드가 까다로운 방식으로 작동한다고 정말로 믿습니까?

그것은 실제로 모든 방법을 동기화 된 {} 블록으로 랩핑하고 더 이상 아무것도 마무리하지 않습니다.

UPD : 차이점은 모든 동기화 작업을 직접 수행하는 대신 동기화 된 컬렉션을 사용하면 실수를 할 기회가 훨씬 적다는 것입니다.

Upd 2 : 소스에서 볼 수 있듯이 'Mutex'-object를 모니터로 사용합니다. 메소드 서명에서 동기화 된 수정자를 사용하는 경우 (즉 synchronized void doSmth()) 현재 객체의 인스턴스 (즉, 즉 this)는 모니터로 사용됩니다. 아래 두 개의 코드 블록은 동일합니다.

1.

synchronized public void doSmth () {
   someLogic ();
   moreLogic ();
}

synchronized public static void doSmthStatic () {
   someStaticLogic ();
   moreStaticLogic ();
}

2.

public void doSmth () {
   synchronized (this) {
      someLogic ();
      moreLogic ();
   }
}

public static void doSmthStatic () {
   synchronized (ClassName.class) {
      someStaticLogic ();
      moreStaticLogic ();
   }
}

스레드 안전이 발생하면 동시성 패키지 데이터 구조를 사용하십시오. 래퍼 클래스를 사용하면 맵에 대한 모든 액세스가 순차 대기열로 줄어 듭니다.

a)지도의 완전히 다른 지점에서 작업을 기다리는 스레드는 동일한 잠금을 기다리고 있습니다. 스레드 수를 기준으로 응용 프로그램 성능에 영향을 줄 수 있습니다.

b)지도에서 복합 작업을 고려하십시오. 단일 잠금 장치가있는 래퍼를 사용하면 도움이되지 않습니다. 예를 들어. "현재 존재한다면 봐"는 종류의 작업을 추가하십시오. 스레드 Syncronization이 다시 문제가됩니다.

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