2016-09-05 2 views
0

여러 스레드에서 공유되는 Set에 대해 반복 작업을해야합니다. 이 같은 코드 :LinkedHashSet을 반복 처리하고 제거가 수행되지 않는 경우 동기화를 건너 뜁니?

그것의 반복 처리를하는 경우, 사용자가 수동으로 돌려 세트에 동기를 잡을 필요가 있습니다 : 나는 synchronizedSet에 대한 자바 독을 읽고

class MyObj{} 
final static Set<MyObj> instances = Collections.synchronizedSet(new LinkedHashSet<MyObj>()); 
// returns the same object from the set if any, or add it if not found 
public MyObj test2(MyObj a){ 

    if(instances.add(a)) 
      return a; 

    for(MyObj o : instances){ 
     if(o.equals(a)) 
      return o; 
    } 

    throw new IllegalStateException("Impossible to reach this line"); 
} 

, 그것은한다고

Set s = Collections.synchronizedSet(new HashSet()); 
    ... synchronized (s) { 
    Iterator i = s.iterator(); // Must be in the synchronized block 
    while (i.hasNext()) 
     foo(i.next()); 
    } 

이 조언을 따르지 않으면 비 결정적인 동작이 발생할 수 있습니다.

는하지만, 나는 또한 LinkedHashSet의이 삽입 순서 반복을 제공 this answer에 읽었다. 그리고 내 설정과는 모든 스레드는

  • 가 하나의 새로운 개체를 추가하려고
  • 추가 작업이이 개체를 테스트하는 동안
  • 명확한를 수행 결코 반복, 거짓을 반환하는 경우에
  • 또는 제거하면 세트가 커질 수 있습니다.
  • 이 모든 가설과

, 내 생각 엔 내가 다른 스레드 내가 그것을 반복하고있는 동안 새로운 객체를 추가하는 경우에도 이후 설정에 동기화를 수행하기 위해, 그것은 말에있을 것입니다 필요가 없다는 것입니다 설정하고 내가 삽입 점에 도달하기 전에 찾고있는 객체를 찾습니다.

이 정보가 맞습니까?

+1

"내 생각 엔 세트에서 동기화를 수행 할 필요가 없다는 것입니다 ..."나는 거기에서 당신을 멈출 것입니다. 너. 세트를 수정하는 경우 (예 : 요소 추가) 항상 동기화해야합니다. –

+1

다음은 그러한 가정을하지 말아야하는 이유에 대한 [좋은 예] (http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html)입니다. 이야기의 도덕은 공개 API를 통해 관찰 할 수있는 것만으로 구현의 내부 동작을 추론 할 수 없다는 것입니다. 자물쇠가없는 컬렉션을 원할 경우, 동기화되어야하지만 그렇지 않은 자물쇠가없는 컬렉션을 사용하십시오. – biziclop

+0

나는 lock-free 콜렉션 사용에 대해 생각하지 않았다. 힌트를 주셔서 감사합니다. – Aldian

답변

2

아니오 Javadoc에 명시된 바와 같이, 당신 해야 동기화,이 구현은 동기화되지 않도록

참고. 복수의 thread가 동시에 링크 해시 세트에 액세스 해, 적어도 1 개 (살)의 thread가 세트를 변경하는 경우는, 외부에서 동기 할 필요가 있습니다.

다른 스레드가 요소를 추가 할 때 스레드를 반복하는 경우 ConcurrentModificationException이 표시됩니다. 이 클래스의 iterator 메소드에 의해 반환

반복자는 르파됩니다 세트가 변경되는 경우 반복자 자신의 remove 방법 이외 방법으로 만든 후, 반복자는 ConcurrentModificationException 발생합니다 .

+0

나는 그들이 실패한 행동을 강요하지 않았 으면 좋겠다. 아무 일도 일어나지 않지만 끝에 새로운 객체가있을 때 배열을 반복하는 것은 무엇이 잘못 되었습니까? – Aldian

+0

@Aldian 취급 가치가있는 일반적인 경우는 아닙니다. –

+1

@Aldian : 누가 "일어날 수 없다"고 말할까요? 'Iterator'가 랩핑되었음을 알지 못하는 'LinkedHashSet' 주위에 동기화 된 래퍼를 생성했기 때문에, 일관성없는 상태로부터 자신을 보호하기를 계속합니다. 보조 노트로, 그 반복자의 현재 구현은 실제로'LinkedHashMap $ LinkedHashIterator'의 하위 타입으로,'LinkedHashMap'의 온 액세스 재정렬에 대한 지원과 함께,'HashMap'과 코드를 공유합니다. 삽입 순서 탐색을 지원하므로 삽입시 반복기가 무효화됩니다. – Holger