2013-02-05 7 views
5

나는 읽을 수 있도록 여러 스레드에서 공유해야하는 문자열 목록 (tagList)을 가지고 있으므로 수정할 수없는 버전을 만들어 스레드에 전달합니다. 스레드는 그 목록 만 읽을 수 있으므로 스레드 안전성 여부는 확실하지 않습니다. 나는 괜찮을 것 같아요?은 수정할 수없는 스레드 목록 안전합니까?

스레드에 unmodifialble 목록을 전달할 때 단일 복사본을 전달하고 스레드가 공유합니까? 아니면 여러 복사본을 만들고 각 스레드에 복사본 하나를 전달합니까? (이 수정 될 수 없기 때문에)

final List<String> tList = Collections.unmodifiableList(tagList); 
List<Future<Void>> calls = new ArrayList<Future<Void>>(); 

FileStatus[] fsta = _fileSystem.listStatus(p);  
for (FileStatus sta : fsta) { 
    final Path path = new Path(sta.getPath(), "data.txt"); 
    if (!_fileSystem.exists(path)) {   
     continue; 
    } 
    else { 
     calls.add(_exec.submit(new Callable<Void>() { 
      @Override 
      public Void call() throws Exception { 
       filterData(path, tList); 
       return null; 
      } 
     })); 
    } 
} 
+1

스레드로부터 안전합니다. – jdb

답변

6

이것은 전적으로 기본 목록이 읽기 작업에서 스레드로부터 안전한지 여부에 달려 있습니다. 수정 불가능한 목록은 추가 동기화없이 기본 목록에 size(), get (int) 등의 모든 읽기 호출을 전달합니다.

예를 들어 해시 코드가 필요할 때마다 계산하는 대신 해시 코드를 캐시하는 List 구현을 상상해보십시오. 이러한 구현의 경우, hashCode() 메서드는 내부적으로 캐시 된 해시 코드 값을 수정할 수 있기 때문에 실제로는 읽기 전용이 아닙니다.

또 다른 예는 색인과 함께 마지막으로 액세스 한 항목에 대한 참조를 캐시하는 LinkedList의 특성이므로 가까운 요소에 대한 추가 접근 시도가 훨씬 빠르게 수행됩니다. 이러한 구현의 경우 get (int) 메서드는 캐시 된 참조 및 인덱스를 업데이트하므로 스레드로부터 안전하지 않으므로 읽기 전용이 아닙니다.

+1

그리고 기본'List'가 수정 될 수 있습니다. 안전하지 않은 경우에도 안전하지 않을 수 있습니다. –

+0

기본 목록이 수정 될 수 있다는 사실은 스레드 안전과는 아무런 관련이 없습니다. –

+3

나는 따라 가지 않는다. 기본'List'가'unmodifiedList'가 읽히는 스레드와 다른 스레드에서 수정되는 경우, 기본'List'에 대한 읽기 작업으로 인해 내부 수정이 발생하지 않더라도 다중 스레드 액세스가됩니다. –

2

그것은 스레드 안전 :

여기 내 코드입니다. 동일한 사본을 전달합니다.

그러나 랩핑 된 목록 (tagList)은 여전히 ​​스레드로부터 안전하지 않습니다. 래핑 된 목록이 공유되는 동안 수정해서는 안됩니다. unmodifiableList()에 의해 반환 된 목록은 래퍼 된 목록에 수정이 허용되지 않기 때문에 안전합니다.

0

귀하는 목록이 변경되지 않는다고 말하면서; 따라서 스레드로부터 안전합니다.

개체를 전달하면 실제로 개체에 대한 참조가 전달되고 실제 개체는 전달되지 않습니다. 단일 복사본이 있고 수정되지 않아서 스레드로부터 안전합니다.

단지 하나의주의; tagList에 직접 액세스하지 마십시오. 이라는 이름의 바꿀 수없는 컬렉션을 통해 항상 액세스합니다. List. 제대로 캡슐화하면이 작업을 수행 할 수 있습니다.