2011-12-13 5 views
2

synchronized 호출 중에 발행 된 잠금 범위에 대한 이해를 높이려고합니다.동기화의 동작 이해

예 :

class CopyOnReadList<T> { 

    private final List<T> items = new ArrayList<T>(); 

    public void add(T item) { 
     items.add(item); 
    } 

    public List<T> makeSnapshot() { 
     List<T> copy = new ArrayList<T>(); 
     synchronized (items) { 
      // Make a copy while holding the lock. 
      for (T t : items) copy.add(t); 
     } 
     return copy; 
    } 

} 

(코드 사랑 this excellent answer에서 차용)이 코드에서

, 할 수있는 하나의 스레드 호출 add 또 다른 makeSnapshot를 호출하는 동안?. 즉, synchronized (items)에 의해 생성 된 잠금이 시도 된 모든 읽기에 영향을 미치지 만 items 또는 makeSnapshot() 메서드를 통해 시도한 읽기에만 영향을 줍니까?

public void add(T item) { 
    synchronized (items) { 
     // Add item while holding the lock. 
     items.add(item); 
    } 
} 

이 제거 부작용은 무엇인가

원래 포스트 실제로 추가 방법에 synchonized 잠금을 사용?

+0

* add * 메소드에서 * synchronized *을 제거하면 * makeSnapshot *을 호출 할 때 * 다른 스레드가 추가 한 모든 항목의 "스냅 샷"을 가져 오는 것이 전혀 보장되지 않습니다. 따라서 지금까지 내가 * 동기화 * 호출 제거의 부작용을 볼 수있는 지금은 코드가 깨졌습니다. 그 외에도 일관성없는 국가에 도달하는 것이 가능할 수도 있습니다 ... –

답변

2

이것은 makeSnapshot()에서 시도한 것 또는 더 일반적으로 synchronized (items) 블록을 가진 다른 모든 메소드에 영향을 미칩니다 (가능한 한 항목 객체와 블록을 잠그려고 시도 함을 의미 함).

add() 메서드에서 동기화 된 블록을 제거하는 부작용은 add()가 항목 객체에서 동기화를 시도하지 않으므로 makeSnapshot()이 실행되는 동안을 포함하여 동시 수정을 허용한다는 것입니다.

add()에서 동기화하지 않으면 스냅 샷이 생성되는 동안 다른 스레드가 항목 컬렉션에 요소를 추가하게 할 수 있습니다.

1

이 코드 스 니펫에서는 다른 사람이 makeSnapshot을 호출하는 동안 하나의 통화 추가를 호출 할 수 있습니까?

확실하게 - 방법 중 하나에서 ConcurrentModificationException으로 실패 할 수 있습니다. 그렇지 않으면 목록의 내용이 손상 될 수 있습니다.

동기 (항목)에 의해 생성 된 잠금이 모든 가 makeSnapshot() 방법으로 시도 만이 항목에 대한 읽기, 또는 시도에 어떤 영향을 미치는가?

도 아니다. 잠금은 객체 items의 동작에 아무런 영향을 미치지 않습니다. 블록 또는 메소드에 대해서만 snychronize를 수행합니다. 즉, 동시에 두 개의 스레드가 해당 블록이나 메소드를 실행할 수 없도록합니다.

1

다른 스레드가 makeSnapshot을 호출하는 동안 하나의 스레드 호출을 추가 할 수 있습니까?

예. synchronized은 다른 스레드가 동일한 개체 (이 경우 CopyOnReadList)에서 동기화 된 다른 코드 블록을 입력 할 수 없도록합니다. add 메소드를 동기화하지 않았으므로 하나의 스레드가 makeSnapshot을 실행 중이더라도 여러 스레드가 add을 동시에 호출 할 수 있습니다.

ArrayList은 스레드로부터 안전하지 않으므로 add 메서드에서 synchronized를 제거하면 코드가 비 threadsafe가됩니다.

규칙은 : 공유 가변 상태에 대한 모든 액세스 (읽기 또는 쓰기)가 동일한 잠금에서 동기화되어야합니다.