앤서니 윌리엄스의 액션 북에서의 동시성 (Concurrency)에서, 그는 split reference count를 사용하여 lock free 스택을 구현합니다. 머리 노드의 초기로드 후. 그는 아래 코드에 나열된 메소드 호출 increase_head_count를 사용합니다.액션 북의 동시성에서 분리 된 참조 카운트를 사용하여 잠금없는 스택 구현
counted_node_ptr old_head = head.load();
increase_head_count(old_head);
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do
{
new_counter = old_counter;
++new_counter.external_count;
}
while (!head.compare_exchange_strong(old_counter, new_counter));
old_counter.external_count = new_counter.external_count;
}
이 링크 https://github.com/subjam/concurrency-in-action/blob/master/ch7/stack_ref.cpp에서 전체 구현을 찾을 수 있습니다.
내 질문은, 하나 이상의 스레드가 동시에 pop()을 실행하려고 시도하고 모든 스레드가 헤드 노드를 읽은 다음 하나만 종료 될 때까지 실행되고 이후에이 구현이 어떻게 작동하는지 다른 질문이 실행되면 발생합니다.
저는 꽤 오랫동안 여기에 갇혀 있습니다. 누군가 이해하면 도와 주시면 정말 기뻐하실 것입니다.
답장을 보내 주셔서 감사합니다.이 질문에 대한 의구심을 가지십시오. 견인 스레드가 increase_head_count 함수를 실행하고 하나가 처음에 일시 중지되었습니다. 이제 한 스레드는 모든 방법을 실행하고 old_node 포인터도 삭제합니다 (링크에서 제공된 전체 구현 참조). 일시 중지 된 스레드가 깨어 났을 때 예외가 발생하지 않습니다 (잘못된 메모리 또는) ++ new_counter.external_count를 실행할 때; 코드는 삭제 된 노드를 참조하므로 (첫 번째 스레드에 의해) – Kasun
첫 번째 스레드 ('increase_head_count()'메서드를 통해)는 삭제하기 전에'head'를 제어합니다. 삭제하기 전에 스택에서 제거하려고 시도합니다. 스택에서 성공적으로 제거되면 두 번째 스레드 ('increase_head_count()'에서 깨어나게됩니다)는 head에 대한 참조를 갖지 않습니다. 위에서 말한 것처럼'old_counter'는 새로운'head'를 가리 키도록 업데이트 될 것이므로 삭제 된 노드에 액세스하려고하지 않을 것입니다. –
이 코드에 대한 나의 관심은 첫 번째 (성공한) 스레드가 마지막으로 푸시 된 노드에 대한 제어권을 얻고 'head'가 이제 원래의 'counted_node_ptr'을 가리키면이 두 번째 스레드의 코드 (메소드'pop') 'ptr'는'NULL'이므로이'head'를 삭제하려고 시도하지 않습니다. 헤드를 삭제하지 않으면'counted_node_ptr' 안에서 반복되는 모든 2 차 스레드가'pop'을 떠나서'T'의 빈 값을 반환합니다. 그러나'head'의 원래 값에 대한'ptr'는 생성자 없이는 초기화되지 않기 때문에'NULL'이되는 것은 아닙니다. –