14장. 쓰레드 동기화 기법 2

JAMM·2021년 10월 3일
0

CS

목록 보기
11/12
post-thumbnail

14장. 쓰레드 동기화 기법 2


1. 실행순서에 있어서의 동기화


  • 쓰레드의 실행순서를 동기화한다.
    • 메모리에 접근하는 쓰레드의 실행순서를 동기화한다.
    • 실행순서 동기화는 메모리 접근 동기화를 포함하는 개념이다.

생산자/소비자 모델


  • 예를 들어, 문자열을 입/출력하는 연산을 생각해보자.
    • 입력이 먼저 일어난 후, 출력이 되어야 한다.
    • 입력/출력이 번갈아가면서 진행되어야 한다.
  • 하나의 쓰레드가 입력과 출력을 모두 담당한다면
    • 기존의 데이터 유입량보다 많은 용량의 데이터가 한번에 들어왔을 때
    • 입력/출력이 반복되어야 하지만
    • 하나의 쓰레드에서 출력을 하는 도중 데이터가 계속 밀어닥치면
    • 입력된 데이터의 손실이 발생할 수 있다.
  • 이러한 문제점을 해결하기 위해 보통 I/O를 디자인 할 때
    • '입력 쓰레드 -> Buffer -> 출력 쓰레드' 형식으로 디자인한다.
    • 항상 입력>출력인 경우 버퍼의 크기를 충분하게 설계한다.
    • 데이터가 외부로부터 들어오는 상황에서 버퍼에 쌓는다.
    • 버퍼가 견디는 한도 내에서 출력이 더디게 일어나도 데이터의 손실이 발생하지 않는다.
    • 이 때, 입력 쓰레드를 생산자 쓰레드라고 하고
    • 출력 쓰레드를 소비자 쓰레드라고 한다.
    • 이를 생산자/소비자 모델이라고 하며, 중요한 것은 순서이다.
    • 생산자가 실행이 완료된 다음에 소비자가 실행되어야 한다.

이벤트(Event) 기반 동기화


이벤트 기반 동기화를 활용하기 위한 문제


  1. 생산자 쓰레드가 버퍼에 데이터를 가져다 놓는다.
  2. 소비자 쓰레드가 이 데이터를 가져간다.

  • 문제: 생산자 쓰레드가 데이터를 다 가져다 놓았는지, 소비자 쓰레드가 알 수 없다.

  • Windows에서 쓰레드의 실행 순서를 동기화한다고 하면, 가장 먼저 떠올리는 것이 이벤트 기반 동기화 기법이다.
  • 세마포어나 뮤텍스와 같이 동기화를 위한 오브젝트가 사용된다.
    • 이를 '이벤트 오브젝트'라고 한다.
  • 일반적으로 쓰레드나 프로세스의 커널 오브젝트 경우, 초기에는 Non-Signaled 상태로 생성된다.
  • 그리고 쓰레드나 프로세스가 종료될 경우에, 해당 커널 오브젝트는 Signaled 상태로 자동으로 변경된다.

  • 하지만, 이벤트 오브젝트는 쓰레드나 프로세스가 종료될 경우에 자동으로 Signaled 상태가 되지 않는다.
  • 즉, 자동으로 Signaled 상태가 되는 특정 상황이라는 것이 존재하지 않는다.

이벤트 기반의 메커니즘 예시


  • 커널 오브젝트 생성(이벤트)
  • 이 커널 오브젝트를 초기에 Non-Signaled 상태로 설정
  • 생산자 쓰레드가 일을 마치고 소비자가 진입해야 할 상황에 생산자 쓰레드가 이 커널 오브젝트의 상태를 Non-Signaled -> Signaled 상태로 변경
  • 소비자 쓰레드가 이 커널 오브젝트가 Signaled 상태로 바뀐 것을 보고, 일을 시작
    • 이를 위해서 소비자 쓰레드는 WaitForSingleObject() 함수를 활용하여 호출하고 블로킹 상태로 커널 오브젝트가 Signaled 상태가 되기를 기다린다.
    • 생산자 쓰레드가 일을 마친 후, 커널 오브젝트가 Signaled 상태로 변경한다. 이 때 호출하는 함수 SetEvent()

이벤트 기반 동기화 모드: 수동/자동 리셋 모드


HANDLE CreateEvent (
    LPSECURITY_ATTRIBUTES lpEventAttributes, // 보안 속성
    BOOL bManualReset, // manual-reset mode 설정
    BOOL bInitialState, // 이벤트의 초기 상태 설정
    LPCTSTR lpName // 이벤트 오브젝트 이름 설정
);

/*
bManualReset
- True: 수동 리셋 모드 이벤트 오브젝트
- False: 자동 리셋 모드 이벤트 오브젝트

bInitialState
- True: Signaled 상태의 이벤트 오브젝트 생성
- False: Non-Signaled 상태의 이벤트 오브젝트 생성
*/

수동 리셋 모드


  • 이벤트 오브젝트 상태를 수동으로 조작
  • Signaled -> Non-Signaled
  • Non-Signaled -> Signaled

자동 리셋 모드


  • Non-Signaled -> Signaled 수동 (SetEven() 함수)
    • 생산자 쓰레드만 자신이 완료된 타이밍을 알 수 있으므로
    • 일을 다 마치고난 후 SetEvent() 함수를 호출
  • Signaled -> Non-Signaled 자동
    • 소비자 쓰레드는 WaitForSingleObject() 함수를 호출하고 블로킹 모드로 이벤트 오브젝트가 Signaled 상태가 될 때 까지 대기
    • 생산자 쓰레드가 SetEvent() 함수를 호출하여 이벤트 오브젝트가 Signaled가 되면 WaitForSingleObject() 함수 반환과 동시에
    • 이벤트 오브젝트가 자동으로 Non-Signaled 상태가 됨

  • 자동 리셋 모드: 한 순간에 하나의 쓰레드만 실행 기회를 얻기 위함
  • 수동 리셋 모드: 둘 이상의 쓰레드가 동시에 실행 기회를 얻기 위함

3. 타이머 기반 동기화


  • Windows에서는 Signaled 상태라는 개념이 중요
  • 어떠한 커널 오브젝트는 특정 상황이 도래하면 Signaled 상태가 된다.
  • 어떠한 커널 오브젝트는 명시적인 함수 호출을 통해 Signaled 상태가 된다.
  • 여기서 소개하는 동기화 오브젝트는 정해진 시간이 지나면 자동으로 Signaled 상태가 되는 특성을 지닌다.

  • 타이머를 기반으로 쓰레드를 동기화한다는 것은 임계 영역 문제 해결을 위한 동기화와는 그 관점이 다르다.
  • 여기서 말하는 동기화는 쓰레드의 실행시간 및 실행주기를 결정하겠다는 의미

  • 수동 리셋 타이머
    • 알람 시계를 생각하면 된다.
    • 새벽 6시에 알람을 맞춰 놓으면 새벽 6시에 시계가 울린다.
    • 이벤트가 내가 지정해준 시간에 Signaled 상태가 됨
  • 주기적 타이머
    • 수동 리셋 타이머에 주기적인 특성이 가해진 형태
    • 새벽 6시에 알람을 맞춰 놓으면, 이후 30분 마다 한 번식 주기적으로 알람이 울릳록 설정
    • 자동으로(주기적으로) 타이머가 Signaled 상태가 되는 타이머를 자동 리셋 타이머라고 함
    • 30분 마다 한 번씩 알람이 울린다는 것은 = 30분에 한 번씩 Signaled 상태가 되는 것

Reference

0개의 댓글