작성
·
317
1
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
if (_popCount == 1)
{
if(--_popCount == 0) // 1)
{
}
}
안녕하세요!
1) 부분에 대한 질문입니다
왜 한번더 체크를 해야하는건가요?
설명해주신 내용에선
끼어든 애가 없으니 삭제 진행이라고 하셨는데요
애초에 popCount == 1 에서 if문 안으로 들어왔다면 더이상 끼들수 있는 애가 없는게 아닌가 싶습니다
누군가가 다시 Pop에 들어온다면
if (popCount == 1)
{
}
else
{
}
처음부터 else로 빠지는게 될 것 같습니다
그리고 _pendingList 도 exchange로 가져오기 떄문에 원자적으로 가져올 수 있는게 아닌가 싶습니다
답변 2
4
자세히 보니 위에 말씀하신 상황이 문제는 아닐 것 같네요.
_pendingList의 내부 데이터가 nullptr이라도,
atomic<Node*> _pendingList; 자체는 정상적으로 이용할 수 있기 때문에
딱히 런타임 에러가 나진 않습니다.
현재 LockFreeStack 코드에서 과도할 정도로 추적하면서
딱 1개의 쓰레드만 Pop중일 때 삭제를 하게 유도하는 이유는
결국 위 코드에서, oldHead = _head; 를 추출해서 CAS를 돌리려는 순간,
다른 누군가가 새치기 해서 참조중인 _head 노드를 Pop해서 delete까지 하면
oldHead->next에 접근할 때 크래시가 날 '수도' 있기 때문입니다.
(100%는 아니지만... allocator에 따라 다르긴 하겠죠)
따라서 설령 삭제 예약을 위해 _pendingList에 등록 되었다 하더라도,
다른 쓰레드가 위처럼 Node* oldHead = _head;로 삭제 예정 노드를
참조하지 않는다는 보장이 없기 때문에
꼭 1개 쓰레드만 Pop중일 때 삭제를 유도하고 있습니다.
다시 질문주신 상황으로 돌아가서, _popCount == 1임을 확인해서
혼자라도 가정하고 데이터를 꺼내는 도중에라도,
다른 쓰레드들이 접근해서 Pop을 할 수가 있을텐데요.
만약 별도의 2개의 쓰레드가 거의 동시에 접근해서
하나는 Node* oldHead = _head; 참조를,
다른 하나는 실제 꺼내서 실제로 _pendingList 등록까지 마친다면
처음에 우려했던 상황이 다시 재현되게 됩니다.
따라서 2중 체크를 해서 정말 삭제할 데이터를
그 어느 누구도 참조하고 있지 않은지를 100% 확실히 해서,
극악의 확률로 일어날 수 있는 문제에 대비하고 있습니다.
1
멀티쓰레드 환경에서는 함수 단위로 생각할 수는 없고,
줄 단위로 끼어드는 상황을 같이 생각해야 합니다.
_popCount ==1 을 체크했다고 그 다음 부분에서도 계속 _popCount가 1이라는 보장이 없습니다.
즉, 위 그림 순서대로 (1)->(2)->(3)이 멀티쓰레드 환경에서 실행되는 경우도 고려해야 합니다.
그러면 분명 (1)번에서 _popCount = 1로 체크해서 (3)을 실행하려는 바로 그 찰나,
다른 쓰레드가 (2)에 의해 _popCount을 1 증가시키고
나머지 로직도 쭉 실행하면서 _pendingList를 참조하고 있을 수도 있겠죠.
만약 --_popCount == 0까지 통과한 다음에,
다른 쓰레드가 뒤늦게 TryPop을 호출하는 상황은 상관없습니다.
이미 안전하게 _pendingList를 exchange를 통해 꺼내온 상태이기 때문이죠.
답변 감사합니다!
`나머지 로직도 쭉 실행하면서 _pendingList를 참조하고 있을 수도 있겠죠.`
위에 답변 주신내용 다시 한번 확인해보니
아래와 같이 _popCount 가 1 이상 되었을때 else로 빠지게 되고
ChainPendingNode를 호출하면서 내부에서 ChainPendingNodeList가 호출 되는데
1. 이때 last->next =pendinglist를 넣는 시점에 nullptr 일 수 있고
2. 바로 아래 compare_exchange_weak 호출시에 런타임 에러
이렇게 이해를 했습니다
이부분이 말씀하신 문제가 될 수 있는 부분이 맞을까요?
많은 도움이 되었습니다
자세한 설명과 답변감사합니다!