문제

다음 수업이 있다고 가정 해 봅시다

public class AccessStatistics {
  private final int noPages, noErrors;
  public AccessStatistics(int noPages, int noErrors) {
    this.noPages = noPages;
    this.noErrors = noErrors;
  }
  public int getNoPages() { return noPages; }
  public int getNoErrors() { return noErrors; }
}

다음 코드를 실행합니다

private AtomicReference<AccessStatistics> stats =
  new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));

public void incrementPageCount(boolean wasError) {
  AccessStatistics prev, newValue;
  do {
    prev = stats.get();
    int noPages = prev.getNoPages() + 1;
    int noErrors = prev.getNoErrors;
    if (wasError) {
      noErrors++;
    }
    newValue = new AccessStatistics(noPages, noErrors);
  } while (!stats.compareAndSet(prev, newValue));
}

마지막 줄에서 while (!stats.compareAndSet(prev, newValue)) 어떻게 compareAndSet 방법 평등을 결정하십시오 ~ 사이 prev 그리고 newValue? 입니다 AccessStatistics 구현하려면 클래스가 필요합니다 equals() 방법? 그렇지 않다면 왜? Javadoc은 다음과 같이 말합니다 AtomicReference.compareAndSet

현재 값 == 예상 값이면 주어진 업데이트 된 값으로 값을 원자 적으로 설정합니다.

... 그러나이 주장은 매우 일반적인 것처럼 보이며 Atomicreference에서 읽은 튜토리얼은 원자 공정으로 랩핑 된 클래스에 대해 equals ()를 구현하는 것을 제안하지 않습니다.

Atomicreference에 래핑 된 클래스가 equals ()를 구현하려면 AccessStatistics 객체를 업데이트하고 원자 검색을 사용하지 않는 메소드를 동기화하는 것이 더 빠를 수 있다고 생각합니다.

도움이 되었습니까?

해결책

== 연산자를 사용한 것처럼 절제를 정확하게 비교합니다. 즉, 참조가 동일한 인스턴스를 가리키고 있어야합니다. Object.equals ()가 사용되지 않습니다.

다른 팁

사실, 그것은 그렇습니다 ~ 아니다 이전과 NewValue를 비교하십시오!

대신 통계 내에 저장된 값을 이전과 비교하고 동일 할 때만 STAT 내에 저장된 값을 NewValue에 비교합니다. 위에서 언급했듯이 평등 연산자 (==)를 사용하여 그렇게합니다. 즉, 이전에 이전에 STATS에 저장된 것과 동일한 객체를 가리키는 경우 통계가 업데이트됩니다.

단순히 객체 참조 평등 (aka ==)을 확인하므로 원자 설명이 보유한 객체 참조가 참조를 얻은 후 변경되면 참조가 변경되지 않으므로 다시 시작해야합니다.

다음은 Atomicreference의 소스 코드 중 일부입니다. Atomicreference는 객체 참조를 나타냅니다. 이 참조는 아래와 같이 원자 회의 인스턴스의 휘발성 멤버 변수입니다.

private volatile V value;

get ()은 변수의 최신 값을 간단히 반환합니다 (휘발물이 "이전에 발생하는"방식으로하는 것처럼).

public final V get()

다음은 원자가의 가장 중요한 방법입니다.

public final boolean  compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}

CompareAndset (expect, update) 메소드는 안전하지 않은 클래스의 Java 클래스의 CompareAndswapoBject () 메소드를 호출합니다. 안전하지 않은이 메소드 호출은 기본 호출을 호출하여 프로세서에 단일 명령을 호출합니다. "예상"및 "업데이트"각 객체를 참조하십시오.

AtomicReference 인스턴스 변수 "값"이 동일한 객체를 "epcist"로 참조하는 경우에만 "update"가이 인스턴스 변수에 지금 지정되고 "true"가 반환됩니다. 또는 거짓이 반환됩니다. 모든 것이 원자 적으로 이루어집니다. 다른 스레드는 그 사이를 가로 채울 수 없습니다. 이것은 단일 프로세서 작업 (현대 컴퓨터 아키텍처의 마법)이므로 동기화 된 블록을 사용하는 것보다 종종 빠릅니다. 그러나 여러 변수를 원자 적으로 업데이트해야 할 때 원자 회의는 도움이되지 않습니다.

Eclipse에서 실행할 수있는 완전한 신부 런닝 코드를 추가하고 싶습니다. 그것은 많은 혼란을 해결할 것입니다. 여기에서 22 명의 사용자 (신화 스레드)가 20 석을 예약하려고합니다. 다음은 코드 스 니펫 다음 전체 코드입니다.

22 명의 사용자가 20 석을 예약하려고하는 코드 스 니펫.

for (int i = 0; i < 20; i++) {// 20 seats
            seats.add(new AtomicReference<Integer>());
        }
        Thread[] ths = new Thread[22];// 22 users
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new MyTh(seats, i);
            ths[i].start();
        }

다음은 작고 간결한 전체 코드를보고 싶은 사람들을위한 Github 링크입니다.https://github.com/sankar4git/atomicreference/blob/master/solution.java

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top