[CS] Thread

얄루얄루·2022년 9월 11일
0

Computer Science

목록 보기
8/10
post-custom-banner

Thread

Light weight process라고도 불린다.

각기 고유의 Stack, Counter, Register set을 가지는 실행 단위이다.

Thread가 실행되면 각기 고유의 Counter, Stack, Register set을 참조해 프로세스를 실행한다.

아래 그림을 보자.

좌: 프로세스 / 우: 쓰레드의 그림으로 보면 된다.

Thread는 Process 내에 존재하며, 해당 Process에 속한다.

다시 말해, 몇 가지 고유의 영역을 제외하면 해당 Process의 Code (Text), Data (.data, .bss, Heap memory), File descriptors를 그 Process에 속하는 Threads 사이에 공유한다.

Thread의 특징

  • 하나의 Process에 여러 개의 Thread 생성 가능
  • Thread들은 동시 실행 가능 -> Multi-Threading
  • 소속된 Process의 데이터 모두 접근 가능 -> IPC 기법 등이 불필요

장점

  • 성능: 프로그램의 전체 성능(처리량, 계산 속도, 응답성)을 향상시킴.
  • 리소스 공유: 모든 프로세스의 메모리와 리소스를 공유할 수 있으므로 모든 애플리케이션이 동일한 주소 공간 내에서 여러 활동을 수행할 수 있음.
  • 멀티 프로세서 구조의 활용: 서로 다른 스레드가 서로 다른 프로세서에서 병렬로 실행될 수 있으므로 멀티 프로세서를 최대한 효율적으로 사용할 수 있음.
  • 컨텍스트 스위칭 시간 감소: 스레드는 프로세스 내에서 동작하므로 컨텍스트 스위칭 시간을 최소화하고 가상 메모리 공간은 동일하게 유지.
  • 병렬성: 병렬 프로그래밍 기술을 구현하기가 더 쉬움
    • 멀티 프로세싱은 처음 구조를 잡을 때 만들어야 하지만, 멀티 쓰레딩은 프로그램의 일부 동작에서만 사용하도록 하는 일부의 코드 수정으로 가능하기 때문
  • 간결성: 작업이 분리되어 코드가 간결해 짐.

단점

  • 스레드 중 한 스레드만 문제가 있어도 전체 프로세스가 영향을 받음
    • 멀티 프로세스
    • 멀티 쓰레드
  • 스레드 많이 생성 시, 시스템에 따라 (e.g. Linux) 컨텍스트 스위칭이 많이 일어나 성능 저하
  • 동기화 이슈로 Running condition 발생 가능 : 동기화 코드를 추가해줘야 함 (Mutual exclusion, Semaphore)

Thread 종류

User-level Thread

  • 유저에 의해 관리되며, 커널은 이 녀석의 존재조차 모름
  • 더 빠르게 생성/관리 가능
  • 커널은 해당 종류의 스레드를 마치 Single-Threaded Process처럼 관리함
  • 시스템 콜을 이용하지 않고 유저 레벨 라이브러리를 통해 구현하기 때문에 스레드 사이의 컨텍스트 스위칭 때 이를 자체적으로 하기 때문에 OS에 아무런 호출을 하지 않음.
  • 각각의 프로세스가 각 스레드의 상태/동작을 추적하기 위해 Private Thread Table을 가지고 있음.

Kernel-Level Thread

  • 커널이 스레드의 존재를 알며 OS에 의해 지원됨
  • 시스템 콜을 이용해 생성/구현 됨
  • 커널이 Thread Table을 가지고 있으며 시스템 내에 존재하는 모든 스레드의 상태/동작을 추적함
  • User-level 스레드에 비해 생성/관리 속도가 느림

Deadlock (교착 상태)

프로세스1이 자원1을 할당 받은(lock) 상태에서 자원2의 활용 가능 상태를 기다리고 있는데,
프로세스2는 자원2를 할당 받은 상태에서 자원1의 활용 가능 상태를 기다리고 있다면
어느 하나가 할당 받은 자원을 unlock하지 않는 이상 이 상태는 영영 끝이 나지 않는다.

이 상황을 Deadlock이라고 한다.

Deadlock은 다음의 4가지 조건이 동시에 성립하면 발생할 수 있다.

  • Mutual Exclusion: 둘 이상의 리소스가 공유 불가 + 한 번에 하나의 프로세스만 사용할 수 있음
  • Hold and Wait: 프로세스가 하나 이상의 자원을 보유한 채로 다른 자원을 기다리고 있음
  • No Preemption: 프로세스가 리소스에 대한 lock을 해제하지 않는 한 다른 프로세스에서 해당 리소스를 사용 할 수 없음
  • Circular Wait: 일련의 프로세스가 순환 형태로 서로를 작업이 끝나기를 기다리고 있음

그렇기 때문에, Deadlock 발생을 억제하려면 위 4가지 조건 중 하나를 제거하면 된다. 하지만 Mutual Exclusion를 제거하면 동기화 이슈가 발생해서 곤란하고, Circular form은 강제적으로 없애기엔 너무 억지스럽고 프로그램 설계를 정교하게 하는 방법이 최선이다. 그래서 보통 2가지 방법이 해결책으로 등장하는데,

  • Hold and Wait 제거 -> 프로세스 종료 or 시스템 종료. Deadlock이 굉장히 드물게 발생하는 시스템에서 채택할 수도 있는 방법이다. 그냥 Deadlock 발생이 탐지되면 시스템을 리부팅 하는 것이다. 단순무식한 방법이지만 예를 들어 1년에 3~4건 정도만 발생한다고 한다면 이 문제를 해결하기 위해 많은 코스트를 투자하는 것보다 합리적이다.
  • No Preemption -> 선점 허용. 프로세스 간의 우선순위 등을 비교해 더 높은 쪽이 이미 점유된 자원을 요청하면 그 쪽으로 우선권을 넘겨주는 것이다.

이 외에도 Deadlock 방지법으로 Banker's Algorithm이라는 것이 있다.

하지만,

  • 알고리즘이 너무 복잡하다
  • 각 프로세스가 이용하려는 자원의 최대치를 미리 알아야 한다
  • 방어적으로 자원을 허용하기 때문에 자원 이용률이 낮다

등의 이유 때문에 현실적인 적용이 어려워 현재 채택하고 있지는 않다.

아무튼 알아는 보자.

Banker's Algorithm

Maximum: 각 프로세스가 작업을 마치기 위해 필요한 총 자원 수
Allocated: 현재 각 프로세스에 할당 된 자원 수
Needed: 작업을 마치기 위해 각 프로세스가 필요한 자원 수 (Maximum - Allocated)
Available: 시스템이 프로세스에 할당 가능한 자원 수

Banker's Algorithm의 목적은 적어도 하나의 프로세스가 작업을 끝마치기 위해 필요한 자원은 시스템이 항상 보유하고 있게 하는 것이다.

위 목적이 성립 된 상태를 안정 상태,
그렇지 못한 상태를 불안정 상태라고 한다.

그래서 위 표를 보면 프로세스 0의 Needed보다 Available이 크므로 안정 상태라고 할 수 있다.

Banker's Algorithm은 다음 두 조건 하에서 자원 할당을 허용한다

  • 프로세스의 자원 요청 수가 프로세스가 필요한 자원 수보다 작거나 같다.
    • 2/0/1/1이 필요한데 2/0/1/2를 요청하면 요청이 거절된다.
  • 프로세스의 자원 요청 수가 현재 시스템이 보유한 할당 자원 가능 수보다 작거나 같다.
    • 프로세스4를 보면 1/4/4/4인데 보유 자원은 3/2/1/1이다. 이런 경우에는 요청이 거절된다.

References

profile
시간아 늘어라 하루 48시간으로!
post-custom-banner

0개의 댓글