2017-03-17 8 views
0

나는 위키 피 디아에서, 연습 책에서 동시성에서 ABA 문제를 조사하고 내가 ABA 문제의 근본 원인을 알고있는 것처럼 나는 예전과 같이 알고리즘으로 우리가 같은 그 상태를 확인하는 것이 post자동 가비지 콜렉션이 ABA 프로 우 블을 제거하는 이유는 무엇입니까?

다음 읽고 있지만, 알고리즘은 그 상태를 의미한다 손대지 않았다. 스택

예 :

추가 할 수있는 요소는 우리가 다음과 같은 알고리즘으로를 사용하여 스택 :

create new stack node(save to `newNode` variable) 

while(true) { 
    oldHead = stack.get(); 
    newNode.next = oldHead; // point_1 
    if(stack.compareAndSet(oldhead, newNode)) { // atomically replace head if now head same as was in start of iteration 
     break; 
    }  
} 

단계 ABA의 문제에 어떤 LEED :
초기 상태

a->b->c // a-head, c- tail. 
  1. Thread_1이 값을 추가하려고 시도 함스택 및 OS에이의 compareAndSet 동작 (point_1) 전의 실

  2. Thread_2 다음 팝업 실행 (Thread_1 여전히 정지)

    B-> C // B 헤드, C- 꼬리 중단.

  3. Thread_3 다음 팝업을 실행 (Thread_1은 여전히 ​​중단)

    C // C-머리, C- 꼬리.

  4. Thread_4 다음 a가 (Thread_1 여전히 정지)

    A-> C // A-헤드 C- 꼬리를 밀어 실행된다.

  5. Thread_wake up and cas 작업이 성공적으로 실행되는 경우도 있지만, 경우에 따라 바람직하지 않을 수 있습니다.

Althoug this post 자동 가비지 콜렉션이 문제를 제거 왜 이해가 안 허용됩니다.

저는 C에서 전문가는 아니지만 C에서는 두 개의 다른 객체에 대해 하나의 메모리 범위를 할당 할 수 없다는 것을 알고 있습니다.

더 명확히 할 수 있습니까?

답변

0

아마도 혼란 스러울 부분은 데이터 구조 자체를 내용과 섞어 버린 것입니다.

'적절한'구현에서는 데이터 자체가 아니고 데이터를 포함하는 스택 노드 을 갖게됩니다. 그래서 결국 노드 (a), 노드 (b) 등이 생깁니다. 어떤 스레드가 스택에 c를 밀 때 c를 전달하지만 실제로 푸시 된 노드 (c)가됩니다. 이 의미

, 단지 a, 그것은 다른 포인터 될 것 new Node(a)을 할 것 같은 환경에서, 일 4 단계에서 스택에 입력이되지 않습니다 다른 스레드 1 단계 다음에서 볼 수있다 Node(a)에서 객체는 비즈니스 측면에서 매우 동등 할 수 있습니다 (예를 들어 자바에서는 메소드가 true를 반환합니다). 그러나 포인터 비교는 다릅니다. 여기에서는 자동 GC가 차이를 만드는 부분에 대해 설명합니다. 1 단계의 차단 된 스레드는 나중에 스택에서 제거되어 힙의 어느 곳으로도 강력한 참조가없는 경우에도 스택/레지스터에서 Node (a)의 이전 인스턴스에 대한 참조를 보유합니다. 이렇게하면 해당 노드가 삭제되거나 메모리 주소가 재사용되지 않아 CAS를 속일 수 있습니다.

여기서 언급하는 나쁜 상황은 스레드 1이 여전히 중요한 섹션에있는 동안 원래의 노드 (a)를 삭제하면 (메모리가 아닌) 비 GC 언어에서만 발생할 수 있습니다. 이것은 매우 까다 롭습니다. 메모리의 해제 된 블록에 포인터를 놓고 스레드를 남겨 두었습니다. 실제로 나중에는 더 이상 참조가 취소되지 않을 것이라는 확신을 가질 필요가 있습니다. ABA (당신이 읽을 수있는 많은 나쁜 결과로 끝날 것입니다. 해제 된 블록의 모든 쓰레기).

Node (x) 형식으로 간접 계층을 구현하지 않고 내부 노드를 직접 push/pop/modify하도록 클라이언트 호출을 허용하면 모든 베팅이 해제됩니다. 예를 들어 클라이언트는 동일한 노드를 두 번 밀어 넣을 수 있습니다 나중에 무한 루프로 이어집니다. 귀하의 예제에서는 먼저 삭제 한 다음 동일한 노드를 다시 삽입하지만 데이터 구조와 클라이언트 코드간에 많은 누수가 있다고 가정합니다. 특히 잠금없는 구조로 실험하려는 경우에는 다중 스레드 환경에서 수행하는 것이 매우 위험합니다 .

요약하면 자동 GC는 ABA의 모든 사례를 보호하지 못합니다. 죽은 객체에 대한 참조를 보유하고있는 적극적으로 최적화 된 lock-free 코드를 위해 malloc에 ​​의한 메모리 재사용과 관련된 매우 구체적인 ABA 사례를 보호합니다.