2013-11-24 5 views
2

그들은 일반적으로 다음을 수행하십시오 std :: atomic <T> :: compare_exchange_ *가 ABA 문제를 겪지 않아야하는 이유는 무엇입니까? 일부 포럼 및 책 (동작</i>에서 즉 <i> C++ 동시성)가 멀티 생산자/다중 소비자 스택의 좋은 예, 그리고 <em>팝</em> 구현에에서


// head is an std::atomic<node*> variable 
node *old_head = head.load(); 
while(old_head && !head.compare_exchange_weak(old_head, old_head->next)); 
... 
표준을 사용하는 것 :: 원자 <T> :: compare_exchange_ * ABA 문제를 방지 하시겠습니까?
가의 그런 말을하자

  • old_head-> 다음 스레드가 선취 (직전 compare_exchange_weak)
  • 는 다음 BA 시나리오 스레드 후
  • 을 발생하기 전에 해결됩니다 다시 시작됩니다 head == old_head이 유효합니다. 이 경우 old_head-> 다음
  • 이 실행될 것 compare_exchange_weak이 통과 할 잘못된 메모리 위치를 가리키는 다시 해결되지 않을 것이다, 그러나 값이 old_head-> 다음 여전히 것 하나

ABA 관련 문제가 발생합니다.

는 내가 뭔가를 누락 생각합니다. 내가 여기서 무엇을 놓치고 있니?

건배

답변

2

네, 여기 ABA 문제가 있습니다.

당신이 언급 한 구현 (CiA의 목록 7.3)이 어쨌든 유효하지 않기 때문에 중요하지 않다고 생각합니다. 노드가 새어 나옵니다.

우리가 가장 간단한 참조 횟수 구현을 살펴보면, 잠금 해제 std::shared_ptr (CiA의 7.9 목록)을 사용하는 구현에서 문제가 발생하지 않는다는 것을 알 수 있습니다. 공유 포인터를 사용할 때 새로 생성 된 헤드를 이전 헤드의 메모리 주소에 만들 수 없으므로 스레드가 참조를 보유하고 있으므로 old_head가 삭제되지 않습니다.

스택 구현시 ABA 문제에 대한 공식 Concurrency in Action Manning forums에 스레드가 있습니다.

+0

젠장, 구현 누수와 기타 등등을 알고 있지만이 장의 끝에는이 장의 예제가 ABA 문제로 고생하지 않는다는 단락이 있습니다. 나는 말문이있어 더 조심해야한다. 나는 ABA 문제를 보면서 내가 왜 틀린 지 알기 위해 수 시간을 낭비했지만, 나는 맞았다. 솔직히 나는이 책의 저자와 리뷰어 (있는 경우). – Emanuele