[ 운영체제 ] 5. 스레드 와 프로세스
프로세스 : 프로그램을 메모리 상에서 실행중인 작업
스레드 : 프로세스 안에서 실행되는 여러 흐름 단위
0. 동시성 과 병렬성
스레드와 프로세스에 대한 설명에 앞서 동시성과 병렬성 햇갈리는 개념을 정리하고 가겠습니다.
동시성과 병렬성 모두 사용자로 하여금 한번에 여러 작업을 수행할 수 있게 합니다.
이중에서 동시성은 하나의 작업을 일정 시간동안 진행하고 또다른 작업을 일정시간 수행하는 형태이고
병렬성은 물리적으로 여러 작업을 동시에 진행하는 양상을 보입니다.
그리고 물리적으로 여러 작업을 병렬적으로 처리하기 위해서는 멀티 코어를 필요로 합니다.
반면 동시성은 (하드웨어적으로) 싱글 코어에서도 멀티 스레드를 통해 이루어 낼 수 있습니다.
1. 프로세스와 스레드의 차이
- 데이터 접근
- 프로세스 간에는 각 프로세스의 데이터 접근이 불가하다 (IPC 기법을 통한 접근 필요)
- 스레드는 스레드 별로 스텍 영역만 새롭게 할당되고 메모리 구조중 코드 , data , heap을 공유하기 때문에 프로세스의 데이터를 모두 접근 가능하다
- 안정성
- 프로세스는 프로세스끼리 독립적이기 때문에 오류가 발생했을때 다른 프로세스에 영향을 주지 않는다
- 프로세스내에 하나의 프로세스 오류로 프로세스가 동작을 멈춰 다른 스레드에도 영향을 준다
- 동기화
- 멀티 스레드는 동기화 이슈를 일으키지만 멀티 프로세스는 그렇지 않다
단 ) 스레드를 많이 생성하면 , 다중 프로세스와 마찬가지로 Context Switching 이 많이 일어난다. (특히 리눅스에서는 Thread 를 Process와 같이 다룸)
-> 프로세스와 달리 스택영역을 제외한 나머지를 공유하기에 프로세스만큼의 Context Switching 비용이 발생하지는 않는다.
2. 동기화 이슈
여러 스레드가 동일한 자원(데이터) 접근시 동기화 이슈 발생
해결 방법 1 : Mutex (MUTal EXclusion - 상호 배제)
- 여러 스레드가 변경하는 공유 변수에 대한 Exclusive Acess 필요
- 어느 한 스레드가 공유 변수를 갱신하는 동안 다른 스레드가 동시 접근하지 못하게 막는다
lock.acquure()
for i in range(10000):
g_count += 1
lock.realease
임계 영역(동기화 issue 의 가능성이 있는 영역 > 현재는 포문) 에 대해서 시작때 락을 걸고 임계영역을 통과후 락을 풀어 임계영역 동작시에는 다른 쓰레드로부터 보호한다.
해결방법 2 : Semaphore
P: 검사 (임계 영역에 들어갈 때) -> S값이 1 이상이면, 임계 영역 진입 후, S값 1을 차감합니다. S값이 0이면 대기합니다.
V: 증가 (임계 영역에서 나올 때) -> S값을 1 더하고, 임계 영역을 나옵니다.
S: 세마포어 값 (초기 값만큼 여러 프로세스가 동시 임계 영역 접근 가능) -> 스레드 수를 설정할 수 있습니다.
- S(빈자리) 가 생길때 까지 while 문을 통해 대기한다.
- S(빈자리) 가 생기면 while 문을 빠져나가고 빈자리를 없앤다.
- V , 임계영역을 마치면 S(빈자리) 를 증가시켜 다른 쓰레드의 접근을 허용한다.
위의 sudo 코드는 바쁜대기를 통해 리소스 낭비를 초래하므로
실제 block 하는 시스템 콜을 통해 큐에 넣어놨다가
임계영역을 마치면 큐에서 하나씩 wakeup 하여 실행 시킬 수 있도록한다.
뮤텍스와 세마포어의 차이는?
세마포어는 공유 자원에 세마포어 변수 만큼 쓰레드(또는 프로세스)가 접근할 수 있는 반면
뮤텍스는 오직 1개의 쓰레드 또는 프로세스만이 접근할 수 있고 락을 통해 관리되면 락은 락을 획득한 프로세스가
그 락을 해제해야한다.
세마포어의 카운트를 1로 설정하면 원리는 다르지만 같은 기능을 수행하게된다.
3. 교착상태 (deadlock)
무한대기 상태 : 두개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리고 있기 때문에 다음 단계로 진행하지 못하는 상태 (프로세스 , 스레드 둘다 일어날 수 있음)
4. 기아 상태 (starvation)
특정 프로세스의 우선순위가 낮아서 원하는 자원을 계속 할당 받지 못하는상태