버티의 블로그

[운영체제 #10] Windows API Example 본문

OS_NW/운영체제

[운영체제 #10] Windows API Example

ㅤ버티ㅤ 2024. 5. 22. 10:12
728x90

Windows Synchronization

스레드간의 동기화 : 유저 모드 동기화 기법 사용

  • 스레드 동기화 시 커널 모드보다 유저 모드가 더 효율적
  • 동기화 객체 예시 : Critical Section

프로세스간/스레드간의 동기화 : 커널 모드 동기화 기법 사용

  • 동기화 객체 예시 : Mutex, Semaphore, Event

 

객체의 시그널/비시그널 상태


Windows Semaphore and Event Objects

세마포어 객체

  • CreateSemaphore : count의 초기값, 최대값을 설정해서 세마포어 생성
  • 윈도우에서의 세마포어는 wait = WaitForSingleObject, signal = ReleaseSemaphore
  • WaitFor(single/Multiple)Object : (단일/복수) 객체가 시그널 상태가 되는 것을 대기

 

이벤트 객체

Event Object Basic Concept

  • Set : 시그널 상태로 바꾸고 유지
  • Reset : 비시그널 상태로 바꾸고 유지
  • Pulse : 시그널 상태로 잠시 바꿨다 다시 돌아옴

이벤트 객체 관련 API

  • CreateEvent

  • SetEvent, PulseEvent
    • 수동리셋 : ResetEvent()를 호출해야만 non-signal 상태가 된다.
    • 자동리셋 : 하나의 스레드만 실행시키고 자동으로 non-signal 상태가 된다.

  • 진행 과정

스레드 3개가 실행 중이고 t0에서 SetEvent()를 호출하여 signal상태로 바꾸면, 수동형일 경우 t1에서 T1, t2에서 T2는 WaitForsingleObject를 실행해도 계속 running상태이다. 그래서 t3에서 ResetEvent()를 호출해서 수동으로 non-signal 상태로 바꿔야만 t4에서 T1, t5에서 T2가 WaitForsingleObject로 running에서 wait으로 빠지게 된다.

위와 동일한 상태이지만 이번엔 t0, t3에서 PulseEvent()를 호출했다. t0 시점에서는 대기 중인 스레드가 없었으므로 아무런 일이 일어나지 않았다. 그러나 t3에서는 T1과 T2가 모두 wait상태일 때 PulseEvent()를 호출한 것이므로 T1, T2 둘다 running으로 바뀐다. 또한 수동형임에도 setEvent()와 다르게 WaitForsingleObject를 하면 자동으로 리셋된다는 것을 알 수 있다.

이번엔 자동형에서 SetEvent()를 호출했을 경우다. t0에서 SetEvent()를 했을 때는 signal 상태로 바꾸지만, 대기중인 스레드가 하나도 없었기에 계속 signal상태를 유지한다. 그러다가 t1에서 T1이 WaitForsingleObject했을 때 비로소 non-signal상태로 바뀐다. t4에서 SetEvent()를 했을 때는 대기중인 스레드가 2개 존재했기에 랜덤으로 T1이 running으로 바뀌고 바로 non-signal로 바뀐 것이다.

 

위와 동일한 상태에서 PulseEvent를 한 경우로, PulseEvent()는 SetEvent()와 다르게 대기 중인 스레드가 없어도 signal 상태를 유지하지 않고 바로 non-signal로 리셋한다.

 

  • 수동형은 수동으로 signal상태와 non-signal상태를 바꿔줘야 하고, PulseEvent()를 했을 때 대기 중인 모든 스레드가 running으로 바뀌기 때문에 자동형보다 race condition을 해결하기가 까다롭다.