소개
게시글
질문&답변
Lock-Free Stack #2 강의 질문
저도 비슷한 생각을 했었는데 생각을 좀 정리해본 결과 이러한 상황을 고려해보면 될 것 같습니다.Node* OldHead = Head.load(); while (OldHead && !Head.compare_exchange_weak(OldHead, OldHead->Next)) {};두 스레드가 같이 pop함수에 들어온 상태라고 했을 때, 먼저 한 스레드가 oldHead를 획득하고 카운팅을 하지 않고 이 oldHead를 삭제한다고 해봅시다. 그런데, 삭제하기 전에 이미 획득한 스레드 말고 다른 스레드가 같은 Head를 참조하여 같은 oldHead를 획득한 상태라고 하고, 이후 다른 스레드에서 이것을 삭제하고 나머지 스레드가 뒤늦게 CAS 함수를 호출한다면 OldHead->Next에서 크래쉬가 날 것 같습니다.즉, 1. Node* oldHead = _head 줄을 거의 동시에 진행하여 같은 oldHead를 획득한 스레드가 두 개가 있다. (PopCount 2개)이 때 한 스레드가 CAS를 통과하고 매우 빠르게 삭제를 했는데 이와 동시에 나머지 스레드가 CAS를 들어간다면, 이 아디리가 터진다면 크래쉬가 발생한다. (거의 동시에 들어왔지만 한 쪽은 CAS를 통과하고 delete하는 동안 다른 한 쪽은 가만히 있다가 이제서야 CAS를 시도하는 이 아다리가 무수히 많은 스레드에서 낮은 확률로 발생하지 않을까..? 싶습니다)
- 0
- 1
- 140
질문&답변
WaitForSingleObject의 Auto reset 처리는 원자적인가요
이 질문을 보고 저도 정확한 답변이 궁금하여 제 생각좀 끄적이고 갑니다.아예 틀린 생각일 수 있으니, Rookiss 선생님의 공식 답변을 기다리며 그냥 흘러넘기듯 보시면 될 것 같습니다!제가 이해한 바로는, WaitForSingleObject()를 사용하는 것은 이벤트를 만들 때 부여받은 handle의 이벤트를 참조하여 signal state를 확인하는 것으로 이해했습니다. 즉 인자로 넣어준 handle 이벤트의 state를 확인하여 시그널이 켜져 있는지 확인 후 리턴 값을 보내주는 것 같습니다. 리턴 값들은 공식문서를 보면 잘 나와있습니다.결국 프로듀서 스레드가 SetEvent()를 호출하면, 커널은 인자로 넣어준 이벤트 handle을 참조하여 커널단에서 이 시그널 state를 켜주는 것으로 보이고, 컨슈머 스레드는 WaitForSingleObject()로 이 시그널을 확인하고 켜져있다면 모드를 확인 후 이벤트의 시그널을 다시 꺼주고 리턴 값을 리턴해주는 것 같습니다. 즉, 스레드의 교착상태와 관계없이 커널단에서 생성된 이벤트 풀? 큐? 아님 그냥 단일 이벤트? 의 상태들을 커널이 함수들(시스템 콜)이 호출될 때마다 바꿔주는 것 같습니다. 결국 커널이 시스템 콜을 요청 받았을 때 이벤트의 상태를 바꿔주고 뿌려주는 것이기 때문에 스레드 측면에서 이 처리가 원자적인지 데드락이 걸리는지 확인할 필요가 없다고 생각합니다. 이러한 시스템 콜 때문에 스핀락 같은 기법보다 처리는 깔끔하지만 그만큼 오버헤드를 더 먹는게 아닐까? 생각이 드네요.. (싱글오브젝트가 아닌 여러 스레드를 하나의 이벤트에 다중으로 등록하거나 등등)
- 0
- 3
- 180