자바 fail-fast 와 fail-safe 메커니즘
기본 개념
fail-fast 와 fail-safe 라 는 두 개념 은 모두 집합 적 인 병행 수정 과 관련 이 있다.집합 의 병발 수정 이란 한 스 레 드 가 집합 을 옮 겨 다 니 고 있 을 때 다른 스 레 드(또는 스 레 드 자체)가 집합 을 수정 하 는 것 을 말한다.
fail-fast
fail-fast 메커니즘 은 집합 을 옮 겨 다 니 는 과정 에서 집합 이 바 뀐 것 을 발견 하면 Concurrent ModificationException 을 던 지 는 것 을 말한다.보통 다음 과 같은 두 가지 상황 이 있다.
집합 과정 에서 본 수정 집합4.567917.다 중 스 레 드 의 경우 본 스 레 드 는 집합 과정 에서 다른 스 레 드 는 집합 을 수정 했다
fail-fast 검사
ArrayList 코드 의 경우 코드 에서 expected ModCount 가 modCount 로 초기 화 되 었 음 을 알 수 있 습 니 다.그 중에서 modeCount 는 ArrayList 가 수정(add remove)된 횟수 입 니 다.iterator next 와 reove 인 터 페 이 스 는 expected ModCount 와 modCount 가 같 는 지,다 르 면 이상 을 던 집 니 다.
public Iterator iterator() {
return new Itr();
}
private class Itr implements Iterator {
protected int limit = ArrayList.this.size;
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor < limit;
}
@SuppressWarnings("unchecked")
public E next() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
하나의 예:
ArrayList list = new ArrayList();
list.add("A");
list.add("B");
list.add("C");
for (String str : list) {
list.add("D") ;
}
출력 결과:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) at TestJava.main(TestJava.java:14)
여기 에는 foreach 순환 에 대한 지식 이 포함 되 어 있 습 니 다.javac 컴 파일 러 는 실제 적 으로 iterator 교체 로 처리 합 니 다.
fail-safe
fail-safe 메커니즘 은 집합 을 옮 겨 다 니 는 과정 에서 집합 이 바 뀌 는 것 을 발견 하면 옮 겨 다 니 는 집합 이 정상적으로 진행 되 는 것 을 말한다.CopyOn Write Array List 를 예 로 들 면:
public Iterator iterator() {
return new COWIterator(getArray(), 0);
}
static final class COWIterator implements ListIterator {
/** Snapshot of the array */
private final Object[] snapshot;
/** Index of element to be returned by subsequent call to next. */
private int cursor;
COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements;
}
//...
}
public boolean add(E e) {
synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
}
}
public E remove(int index) {
synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
E oldValue = get(elements, index);
int numMoved = len - index - 1;
if (numMoved == 0)
setArray(Arrays.copyOf(elements, len - 1));
else {
Object[] newElements = new Object[len - 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index + 1, newElements, index,
numMoved);
setArray(newElements);
}
return oldValue;
}
}
final void setArray(Object[] a) {
elements = a;
}
코드 에서 볼 수 있 습 니 다:iterator 는 COWIterator 를 되 돌려 줍 니 다.COWIterator 는 실제 적 으로'현재 elements'를 옮 겨 다 니 고 있 습 니 다.매번 오래된 요 소 를 새로운 배열 에 복사 한 다음 에 조작 합 니 다.
하나의 예
CopyOnWriteArrayList list = new CopyOnWriteArrayList();
list.add("A");
list.add("B");
list.add("C");
for (String str : list) {
System.out.print(str + "\r
");
}
출력 결 과 는:
A B C
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.