2011-03-23 13 views
7

잠금이없는 대기열에있는 이러한 회선은 필요하지 않습니까?

다음은 compareAndSet (Java에서)을 사용하는 잠금없는 큐의 일부 코드입니다.

public void enq(T value) { 
    Node newNode = new Node(value); 
    while(true) { 
     Node last = tail.get(); 
     Node next = last.next.get(); 

     if(last != tail.get()) 
      continue; //???  

     if (next != null) { //improve tail 
      tail.compareAndSet(last, next); 
      continue; 
     } 

     if (last.next.compareAndSet(null, newNode)) { //update last node 
      tail.compareAndSet(last, newNode); //update tail 
      return; 
     } 
    } 
} 

public T deq() throws EmptyException { 
    while(true) { 
     Node first = head.get(); 
     Node last = tail.get(); 
     Node next = first.next.get(); 

     if(first != head.get()) 
      continue; //??? 

     if(first == last) { 
      if (next == null) 
       throw new EmptyException(); 

      tail.compareAndSet(last, next); 
      continue; 
     } 

     T value = next.value; 
     if (head.compareAnsdSet(first, next)) { 
      return value; 
     } 
    } 
} 

(머리와 꼬리는 대기열의 구성원 임)

deq 및 enq 함수에서 첫 번째 수표는 나에게는 불필요한 것처럼 보인다. ("???"로 주석 처리 된 것들) 어떤 종류의 최적화를 위해서 존재하는 것 같습니다.

내가 여기에 뭔가 빠져 있니? 이 검사가 코드의 정확성에 영향을 줍니까?

(코드는 "Art of Multi-processor Programming"에서 가져온 것입니다. 그러나 ifs와 elses를 중첩하지 않고 코드를 동일하게 유지하면서 코드 스타일을 리팩터링했습니다.)

+0

그들은 지역 변수가 일관성있게 설정되었는지 확인하는 것처럼 보이지만 코드의 정확성에 영향을 미치는지 여부를 대답하기 위해 다른 변수에 남겨 둘 것입니다. –

답변

3

예를 theíúvúth 연례 심포지엄을 roceedingsof, 그 IFS는 최적화로 유일한 값을 가지고, 그것은이다 다소 큰 것 : CAS는 메모리에서 읽은 것과 비교할 때 엄청나게 비싸므로 그 동안에 값이 변하지 않았는지 확인하고 후속 CAS에서 오류가 발생할 확률을 줄임으로써 CAS 재시도 횟수를 줄이는 데 도움이됩니다 성능 향상에 도움이됩니다.

& & 꼬리 업데이트 체크를 헤드 내부로 이동할 수도 있습니다 .CAS, 추가 최적화 : 헤드가 업데이트 된 경우에만 꼬리가 뒤떨어 질 수 있으므로 CAS 성공했다. tail.get을 거기서 이동할 수도 있습니다. 다른 곳에서는 필요가 없으므로. 아래 예제 코드. 희망이 도움이!

public T deq() throws EmptyException { 
while(true) { 
    Node first = head.get(); 
    Node next = first.next.get(); 

    if (first != head.get()) 
     continue; 

    if (next == null) { 
     throw new EmptyException(); 
    } 

    T value = next.value; 

    if (head.compareAndSet(first, next)) { 
     Node last = tail.get(); 

     if (first == last) { 
      tail.compareAndSet(last, next); 
     } 

     return value; 
    } 
} 

}

+0

니스, 나는 뭔가를 배웠다. 감사. – Jaydee

2

그들은 필요하지 않습니다 (코드 동등한를 유지하면서 코드는, 내가 덜 중첩 된 IFS를 가지고 코드 스타일을 리팩토링했던 불구하고, "다중 프로세서 프로그래밍의 예술"에서 가져온를 elses입니다)하지만, 성능상의 이유로 사용되면 원자 조작을 사용하지 않고 점검이 발생합니다. MSDN에서

예 비용 :

  • 메모리 배리어는 20-90 회 복용으로 측정 하였다.
  • 인터 로크 된 증가는 36-90 사이클을 취하는 것으로 측정되었다.
  • 임계 단면의 획득 또는 해제는 40-100 사이클을 취하는 것으로 측정되었다.
  • 뮤텍스의 획득 또는 해제는 약 750-2500 사이클을 측정 한 것으로 측정되었습니다. 이러한 특정 기법에 대한

참조 :

[루돌프 & Segall 84] 루돌프 L. 및 Segall는 Z.의 Dy-NAMIC 분산 캐시 반응식 병렬 프로세서 forMIMD. Invù가 가비지 수집을 가지고 주어진, 컴 - 터 아키텍처에 자바의 페이지 340i> 347, 1984

0

는 연결리스트 알고리즘을 비 차단합니다. 자세한 내용은 JCP 서적 (15.4.2.비 차단 링크드 목록)

관련 문제