[운영체제] 스레드(Thread)의 이해

seonja kim·2021년 10월 11일
0

개념

  • light weight process라고도 함
  • 프로세스는 프로세스 간 데이터 접근이 불가능하기에 IPC를 이용했음 (스레드와 프로세스의 차이점)
  • 스레드
    - 하나의 프로세스여러개의 스레드 생성 가능
    - 스레드들은 동시에 실행 가능
    - 프로세스 안에 있으므로 프로세스의 데이터를 모두 접근 가능 (IPC 불필요함)

멀티 프로세싱과 Thread

  • 최근 CPU는 멀티 코어가 대부분이므로 Thread를 여러개만들어 멀티 코어의 활용도를 높임

장단점

장점

  1. 사용자에 대한 응답성 향상
  2. 자원 공유 효율
    • IPC 기법과 같이 프로세스 간 자원공유를 위한 번거로운 작업이 필요 없음
    • 프로세스 안에서 데이터 모두 접근 가능
  3. 작접이 분리되어 코드가 간결

단점

  1. 스레드 중 한 스레드만 문제가 있어도 전체 프로세스가 영향을 받음

  2. 스레드를 많이 생성하면 Context Switching이 많이 일어나 성능 저하
    - 예) 리눅스 OS에서는 Thread를 Process와 같이 다룸
    - 스레드를 많이 생성하면 모든 스레드를 스케쥴링해야 하므로, Context Switching이 빈번할 수 밖에 없음

Thread vs Process

프로세스스레드
독립적프로세스의 서브셋
각각 독립적인 자원을 가짐프로세스 자원 공유
자신만의 주소영역을 가짐주소영역 공유
프로세스 간에는 IPC 기법능로 통신해야 함하나의 프로세스 내에서 자유롭게 접근 가능

동기화 (Synchronization)

  • 동기화란 작업들 사이에 실행 시기를 맞추는 것
  • 여러 스레드가 동일한 자원 (데이터) 접근시 동기화 이슈 발생
    - 동일 자원을 여러 스레드가 동시 수정시, 각 스레드 결과에 영향을 줌

동기화 이유 해결 방안

  • Mutual exclution (상호 배제)
  • 스레드는 프로세스 모든 데이터를 접근할 수 있으므로
    - 여러 스레드가 변경하는 공유 변수에 대해 Exclusive access 필요
    • 어느 한 스레드가 공유 변수를 갱신하는 동안 다른 스레드가 동시 접근하지 못하도록 막음
  • 예시 :
lock.acquire()
for i in range(100000):
	g_count += 1
lock.release()

스레드와 세마포어 (Semaphore)

  • Critical Section(임계 구역)에 대한 접근을 막기 위해 locking 메커니즘이 필요
    - Mutex(binary semaphore)
    : 임계구역에 하나의 스레드만 들어갈 수 있음
    - Semaphore
    : 임계구역에 여러 스레드가 들어갈 수 있음
    : counter를 두어서 동시에 리소스에 접근할 수 있는 허용 가능한 스레드 수를 제어

세마포어 (Semaphore)

  • P: 검사 (임계영역에 들어갈 때)
    - S값이 1이상이면 임계 영역 진입 후 S값 1차감 (S값이 0이면 대기)
  • V: 증가 (임계영역에서 나올 때)
    - S값을 1더하고, 임계영역을 나옴
  • S: 세마포어 값 (초기 값만큼 여러 프로세스가 동시 임계 영역 접근 가능)
P(S): wait(S) {
		while S <=0 // 대기
    	;
    S--; // 다른 프로세스 접근 제한
}

V(S): signal(S) {
	S++; // 다른 프로세스 접근 허용
}

문제점

  • wait()은 S가 0이라면 임계영역에 들어가기 위해 반복문을 수행하게 됨 (busy waiting이라고 함)

해결책 (대기큐)

  • S가 음수일 경우, busy waiting 대신 대기큐에 넣는다.
wait(S) {
		S->count--;
    if (S->count < 0) {
    	add this process to S->queue;
        block()
    }
}

signal(S) {
		S->count++;
    if (S->count <= 0) {
    	remove a process P from S->queue;
        wakeup(P)
    }
}
  • wait이 실행되었지만 세마포어에 빈자리가 없는 상태라면 현재 스레드를 block해서 기다리게 만듬
  • 이후 세마포어를 먼저 획득한 스레드가 signal을 불러 접근 허용 스레드를 하나 증가(s->count++)시키면
    - 1) 기다리던 스레드가 없었고 (증가 이전에 s->count가 0 또는 그 이상) 이제 하나의 스레드가 더 접근할 수 있는 경우 (s->count가 1 또는 그 이상)
    • 2) 기다리던 스레드가 있었고 (증가 이전에 s->count가 -1 또는 그 이하) 이제 하나의 스레드가 더 접근할 수 있는 경우 (s->count가 0 또는 그 이하)
  • 1)의 경우에는 기다리던 스레드가 없었고 증가 이후에 wait(S)을 호출하는 스레드들은 s->count를 감소시키며 block없이 진행할 수 있으므로 signal에서 wakeup을 불러올 필요가 없음
  • 2)의 경우에는 기다리던 스레드가 있었고 증가 이후에도 wait(S)를 호출하는 함수들은 다시 s->count를 음수로 만들면서 block할 예정이므로 signal에서 wakeup을 통해서 기다리던 스레드를 깨워주어야 함

참고: 주요 세마포어 함수 (POSIX 세마포어)

  • sem_open(): 세마포어를 생성
  • sem_wait(): 임계영역 접근 전, 세마포어를 잠그고 세마포어가 잠겨있다면 풀릴 때까지 대기
  • sem_post(): 공유자원에 대한 접근이 끝났을 때 세마포어 잠금을 해제한다.

교착 상태(Deadlock)와 기아상태(Starvation)

  • 교착상태와 기아상태
    - 교착상태는 여러 프로세스가 동일 자원 점유를 요청할 때 발생
    • 기아상태는 여러 프로세스가 부족한 자원을 점유하기 위해 경쟁할 때, 특정 프로세스는 영원히 자원 할당이 안되는 경우를 주로 의미

교착상태란?

  • 무한대기상태: 두 개 이상의 작업이 서로 상대방의 작업이 끝나기만을 기다리고 있기때문에 다음 단계로 진행하지 못하는 상태

교착상태 발생 조건

  1. 상호배제(Mutual exclusion): 프로세스들이 필요로 하는 자원에 대해 배타적인 통제권을 요구한다.
  2. 점유대기(Hold and wait): 프로세스가 할당된 자원을 가진 상태에서 다른 자원을 기다린다.
  3. 비선점(No preemption): 프로세스가 어떤 자원의 사용을 끝낼 때까지 그 자원을 뺏을 수 없다.
  4. 순환대기(Circular wait): 각 프로세스는 순환적으로 다음 프로세스가 요구하는 자원을 가지고 있다.
  • 위의 조건이 모두 성립될 때, 교착상태 발생 가능성이 있음

: 교착상태를 해소하기 위해서는 위의 발생 조건들 중 일부를 해소할 수 있도록 작업수행

기아상태란?

  • 특정 프로세스의 우선순위가 낮아서 원하는 자원을 계속 할당받지 못 하는 상태

해결방안

  • 프로세스 우선순위를 수시로 변경해서 각 프로세스가 높은 우선순위를 가질 기회주기
  • 오래 기다린 프로세스의 우선순위를 높여주기
  • 우선순위가 아닌 요청 순서대로 처리하는 FIFO기반 요청큐 사용
profile
Adventurer

0개의 댓글