Collections.synchronizedList 및 동기화 됨
List<String> list = Collections.synchronizedList(new ArrayList<String>());
synchronized (list) {
list.add("message");
}
"synchronized (list) {}"블록이 여기에 정말로 필요합니까?
예제에 넣은대로 동기화 할 필요가 없습니다. 그러나 매우 중요한 것은 목록을 반복 할 때 목록을 동기화해야한다는 것입니다 (Javadoc에 언급 됨).
사용자가이를 반복 할 때 반환 된 목록에서 수동으로 동기화해야합니다.
List list = Collections.synchronizedList(new ArrayList()); ... synchronized(list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }
synchronized
블록 의 정확한 내용에 따라 다릅니다 .
블록이 목록에서 단일 원자 연산을 수행하는 경우 (예제에서와 같이)
synchronized
는 불필요합니다.블록이 목록에서 여러 작업을 수행하고 복합 작업 기간 동안 잠금을 유지해야하는 경우 에는 불필요한 작업
synchronized
이 아닙니다 . 이에 대한 한 가지 일반적인 예는 목록을 반복하는 것입니다.
Collections.synchronizedList add 메서드의 기본 코드는 다음과 같습니다.
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
따라서 귀하의 예에서는 동기화를 추가 할 필요가 없습니다.
또한 예를 들어 Collections.sort ()와 같이 반복자를 사용하는 모든 메서드는 동기화 된 블록 내에서 캡슐화되어야합니다.
이 Oracle 문서 읽기
"반복 할 때 사용자가 반환 된 목록에서 수동으로 동기화해야합니다."
다른 사람들이 언급 한 것처럼 동기화 된 컬렉션은 스레드로부터 안전 하지만 이러한 컬렉션에 대한 복합 작업은 기본적으로 스레드로부터 안전하다고 보장되지 않습니다.
JCIP에 따르면 일반적인 복합 작업은 다음과 같습니다.
- 되풀이
- 항해
- 부재시
- 확인 후 행동
OP의 동기화 된 코드 블록은 복합 동작이 아니므로 추가 여부에 관계없이 차이가 없습니다.
JCIP에서 예제를 가져 와서 잠금으로 복합 동작을 보호해야하는 이유를 명확히하기 위해 약간 수정 해 보겠습니다.
list
래핑 된 동일한 컬렉션에서 작동하는 두 가지 메서드가 있습니다.Collections.synchronizedList
public Object getLast(List<String> list){
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
public void deleteLast(List<String> list){
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}
방법 경우 getLast
와는 deleteLast
두 개의 서로 다른 스레드에서 동시에 호출, 인터리빙 발생할 수 있습니다 아래에 getLast
발생합니다 ArrayIndexOutOfBoundsException
. 전류 lastIndex
가 10 이라고 가정합니다 .
스레드 A (deleteLast)->
스레드 B 제거 (getLast) --------------------> get
Thread A remove
는 get
Thread B 에서 작업 전 요소입니다 . 따라서 Thread B는 여전히 10 lastIndex
을 호출하는 list.get
메서드 로 사용 하므로 동시 문제가 발생합니다.
참고URL : https://stackoverflow.com/questions/9468187/collections-synchronizedlist-and-synchronized
'Nice programing' 카테고리의 다른 글
iPhone없이 Apple 푸시 알림 서비스를 테스트하려면 어떻게해야합니까? (0) | 2020.11.16 |
---|---|
HashMap : 하나의 키, 여러 값 (0) | 2020.11.16 |
printStackTrace (); 피하십시오. (0) | 2020.11.16 |
Visual Studio는 수정되지 않은 프로젝트를 다시 빌드합니다. (0) | 2020.11.16 |
서비스는 현재 제어 메시지를 수락 할 수 없습니다. (0) | 2020.11.16 |