인프런 커뮤니티 질문&답변

맞수님의 프로필 이미지
맞수

작성한 질문수

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

Event

WaitForSingleObject의 Auto reset 처리는 원자적인가요

작성

·

167

·

수정됨

0

auto_reset가 설정된 event를 SetEvent()할 때, WaitForSingleObject()로 sleep 중인 스레드들을 실행시켜주고 다시 Signal이 리셋되는 것으로 이해했습니다.

  1. 여기서 Signal을 확인하고 리셋하는 과정이 CAS같이 원자적으로 동시에 작동하나요? 아니면, 중도에 WaitForSingleObject()를 호출한 스레드 측에서 리셋이 되지 않아 통과할 가능성이 있나요?

     

답변 3

0

커널에서 이뤄지는 거라서 thread-safe 합니다.

0

이 질문을 보고 저도 정확한 답변이 궁금하여 제 생각좀 끄적이고 갑니다.

아예 틀린 생각일 수 있으니, Rookiss 선생님의 공식 답변을 기다리며 그냥 흘러넘기듯 보시면 될 것 같습니다!

제가 이해한 바로는, WaitForSingleObject()를 사용하는 것은 이벤트를 만들 때 부여받은 handle의 이벤트를 참조하여 signal state를 확인하는 것으로 이해했습니다. 즉 인자로 넣어준 handle 이벤트의 state를 확인하여 시그널이 켜져 있는지 확인 후 리턴 값을 보내주는 것 같습니다. 리턴 값들은 공식문서를 보면 잘 나와있습니다.

결국 프로듀서 스레드가 SetEvent()를 호출하면, 커널은 인자로 넣어준 이벤트 handle을 참조하여 커널단에서 이 시그널 state를 켜주는 것으로 보이고, 컨슈머 스레드는 WaitForSingleObject()로 이 시그널을 확인하고 켜져있다면 모드를 확인 후 이벤트의 시그널을 다시 꺼주고 리턴 값을 리턴해주는 것 같습니다. 즉, 스레드의 교착상태와 관계없이 커널단에서 생성된 이벤트 풀? 큐? 아님 그냥 단일 이벤트? 의 상태들을 커널이 함수들(시스템 콜)이 호출될 때마다 바꿔주는 것 같습니다.

결국 커널이 시스템 콜을 요청 받았을 때 이벤트의 상태를 바꿔주고 뿌려주는 것이기 때문에 스레드 측면에서 이 처리가 원자적인지 데드락이 걸리는지 확인할 필요가 없다고 생각합니다. 이러한 시스템 콜 때문에 스핀락 같은 기법보다 처리는 깔끔하지만 그만큼 오버헤드를 더 먹는게 아닐까? 생각이 드네요.. (싱글오브젝트가 아닌 여러 스레드를 하나의 이벤트에 다중으로 등록하거나 등등)

맞수님의 프로필 이미지
맞수
질문자

우선 정성스러운 의견 감사합니다. 다만..글을 읽어보고 커널과 시스템 콜에 대해 이해도가 부족하다고 느껴서 좀 더 공부를 해보았는데 아직 헷갈리는 부분이 있습니다.

 

슈머 스레드는 WaitForSingleObject()로 이 시그널을 확인하고 켜져있다면 모드를 확인 후 이벤트의 시그널을 다시 꺼주고 리턴 값을 리턴해주는 것 같습니다.

여기서 시그널을 확인하는 동작과 시그널을 다시 꺼주는 동작이 분리되어 있기에 유저 스레드 환경에서 비 원자적으로 구현되었다면 안전하지 못하다 생각됩니다. 하지만, 시스템 콜에서 처리하는 것이니 확인할 필요가 없다고 하셨습니다.

 

이는 여러 시스템 콜이 들어오더라도 커널의 함수 실행은 싱글 스레드 처럼 작동한다는 말씀일까요? 아니면 시스템 콜 발생시 다른 유저 스레드의 시스템 콜을 일시적으로 차단하는 걸까요?

의견만 말씀해주셔도 됩니다. 감사합니다.

음.. 제 생각에는, 작성자님 질문 글을 다시 보면

 

결국 어떤 두 스레드가 동시에 WaitForSingleObject()를 호출하여 signal을 확인할 때(리턴 받을 때) 만약 auto reset이 비원자적?이라 가정하고, 첫 번째 쓰레드가 시그널을 받고 끄는 과정중에 다른 한 스레드가 거의 동시에 요청하여 꺼지지 않은 시그널을 받은 경우의 문제를 말하는 것 같습니다.

https://so-what-93.tistory.com/40\

https://learn.microsoft.com/en-us/windows/win32/sysinfo/kernel-objects

 

근데 위의 글들을 보면, 커널 오브젝트의 signal 관리(연산)는 os가 직접 관리하는 것 같습니다. 즉 커널 오브젝트의 생성 및 관리는 중요도가 가장 높은 작업이고 이는 일반적인 공유자원 처럼 쓰레드들이 접근하여 경쟁상태가 벌어지지 않고, os가 알아서 요청들을 받아들이고 기각하는 것 같습니다.
즉, 저 시그널의 관리들을 critical section이라 보지 않고 그저 커널 오브젝트라는 다른 개념으로 보면? 될 것 같습니다.. 그래서 공식 문서의 WaitForSingleObject() 리턴 값에는 WAIT_FAILEDWAIT_ABANDONED이 있는데, 위에서 상정한 접근이 발생한다면 이러한 값들이 아마 리턴되지 않을까 하고 추측해봅니다. 물론 테스트를 직접해봐야 알겠지만요..

결국 처리 자체는 원자적이라고 볼 수 있지만 이 처리는 일반적인 공유자원들과는 다른 메커니즘?이 있지 않나 생각합니다. 저도 os지식이 아주 부족해서 작성해주신 답글 보고 이것저것 찾아보며 나온 결론이네요. 물론 신빙성은 아주 낮지만요..
더 깊게 들어갈수록 뭔가 머리만 아파지는 것 같기도 하네요.. 일단은 대충이라도 납득하고 선생님의 정식 답변을 기다리며 다음 강의들 공부하다보면 알게 될 날이 분명 올거라고 생각합니다!

맞수님의 프로필 이미지
맞수
질문자

커널, OS 관련 지식은 학습 외 인데 찾아 봐주시는 것 만으로 감사합니다. 말씀하신대로 완강해보고 리뷰해보도록 하겠습니다. 좋은 하루 보내세요

0

안녕하세요, 인프런 AI 인턴입니다.

님의 질문에 대한 답변은 제공된 정보 내에서 해결할 수 있는 부분이 없습니다. 프로그래밍 관련하여 더 자세한 설명이나 관련 질문이 있다면, 추가적으로 문의해주시면 감사하겠습니다. 프로그래밍 언어나 개념에 대한 구체적인 질문이라면 도와드릴 수 있을지도 모릅니다.

맞수님의 프로필 이미지
맞수

작성한 질문수

질문하기