본문 바로가기
OS(운영체제)

쓰레드 (Thread)

by 걸어가는 신사 2021. 12. 9.

* 들어가기 전에

  • 스레드가 대중화되기 전에는 프로세스는 별도의 프로세스를 생성하여 같이 일을 처리하였다.
  • 프로세스 생성 작업은 매우 많은 시간을 소비하고 많은 자원을 필요로 한다.
  • 새 프로세스가 해야 할 일이 기존 프로세스가 하는 일과 동일하다면 왜 이 많은 오버헤드를 감수해야 하는가?
  • 프로세스 안에 여러 스레드를 만들어 나가는 것이 더 효율적이다.

 

1. 쓰레드 (Thread)

프로세스(process) 내에서 실제로 작업을 수행하는 주체, CPU 이용의 기본 단위
  • 스레드는 스레드 ID, 프로그램 카운터(PC), 레지스터 집합, 그리고 스택으로 구성된다.

(1) 장점

  • 응답성 (Responsiveness)
    • 응용 프로그램의 일부분이 봉쇄되거나, 응용 프로그램이 긴 작업을 수행하더라도 프로그램의 수행이 계속되는 것을 허용함으로써, 사용자에 대한 응답성을 증가시킨다.
  • 자원 공유 (Resource Sharing)
    • 스레드는 자동으로 그들이 속한 프로세스의 자원들과 메모리를 공유한다
  • 경제성 (Economy)
    • 스레드는 자신이 속한 프로세스의 자원들을 공유하기 때문에, 스레드를 생성하고 문맥 교환하는 것이 더욱더 경제적이다. 
    • 스레드 생성은 프로세스 생성보다 시간과 메모리를 덜 소비한다.
    • 문맥 교환은 일반적으로 프로세스 사이보다 스레드 사이에서 더 빠르다.
  • 규모 적응성 (Scalability)
    • 다중 스레드의 이점은 다중 처리기 구조에서 더욱 증가한다.

(2) 병행성과 병렬성 (Concurrency vs Parallelism)

  • 병행성 (Concurrency)
    • core가 1개이지만, 여러 개처럼 느껴지도록 해준다. (병렬성의 환상을 제공)

  • 병렬성 (Parallelism)
    • 둘 이상의 작업을 동시에 수행할 수 있다.

 

2. 다중 스레드 모델 (Multithreading Model)

  • 사용자 스레드 (User thread) : 사용자 수준에서 제공된다.
    • POSIX Pthreads
    • Windows threads
    • Java threads
  • 커널 스레드 (Kernel thread) : 커널 수준에서 제공된다.
    • Windows
    • Solaris
    • Linux
    • Mac OS X
  • 사용자 스레드와 커널 스레드는 어떤 연관 관계가 존재해야 한다.

(1) 다대일 모델 (Many-to-One Model)

  • 많은 사용자 수준 스레드를 하나의 커널 스레드로 매핑한다.
  • 한 사용자 수준 스레드가 봉쇄형 시스템 콜을 할 경우, 전체 프로세스가 봉쇄된다.
  • 한 번에 하나의 스레드만이 커널에 접근할 수 있기 때문에, 다중 스레드가 다중 코어 시스템에서 병렬로 실행될 수 없다.

(2) 일대일 모델 (One-to-One Model)

  • 사용자 수순 스레드를 각각 하나의 커널 스레드로 매핑한다.
  • 하나의 스레드가 봉쇄적 시스템 콜을 호출하더라도 다른 스레드가 실행될 수 있기 때문에 더 많은 병렬성을 제공한다.
  • 다중 처리기에서 다중 스레드가 병렬로 수행되는 것을 허용한다.
  • 단점
    • 사용자 스레드를 만들려면 해당 커널 스레드를 만들어야 하며 많은 수의 커널 스레드가 시스템 성능에 부담을 줄 수 있다.
  • 현대의 대부분의 OS에서 사용되고 있다
    • Window
    • Linux
    • Solaris 9 and later

(3) 다대다 모델 (Many-to-Many Model)

  • 여러 개의 사용자 수준 스레드를 그보다 작은 수, 혹은 같은 수의 커널 스레드로 매핑된다.
  • 운영체제가 충분한 수의 커널 스레드를 생성하도록 한다.
  • 실제로는 구현하기 어렵다.
    • 시스템에서 처리 코어 수가 증가함에 따라 커널 스레드 수를 제한하는 것의 중요성이 줄어들었다
    • 대부분의 OS에서는 일대일 모델을 사용한다.
  • 두 수준 모델 (Two-level Model) - 다대다 모델의 변형

  • 많은 사용자 스레드를 적거나 같은 수의 커널 스레드로 매핑하면서 한 사용자 스레드가 하나의 커널 스레드에만 연관되는 것을 허용한다.

 

3. 스레드 라이브러리 (Thread Library)

  • 스레드 라이브러리는 스레드를 생성하고 관리하기 위한 API를 제공한다.
    • 커널의 지원 없이 완전히 사용자 공간에서만 라이브러리를 제공
    • 운영체제에 의해 지원되는 커널 수준 라이브러리를 구현
  • POSIX Pthreads
    • 커널 수준 라이브러리
  • Windows
    • 커널 수준 라이브러리
  • Java

 

4. 암묵적 스레딩 (Implicit Threading)

스레드의 생성과 관리 책임을 개발자로부터 컴파일러와 실행시간 라이브러리에게 넘겨주는 것

(1) 스레드 풀 (Thread Pool)

프로세스를 시작할 때 일정한 수의 스레드들을 미리 풀로 만들어두는 것
  • 스레드 풀의 사용 이유
    • 서비스할 때마다 스레드를 생성하는 데 시간이 소요된다.
    • 모든 요청마다 새 스레드를 만들어서 서비스해 준다면 시스템에서 동시에 실행할 수 있는 최대 스레드 수의 한계를 정해줘야 한다.
  • 스레드 풀의 동작
    • 스레드들은 평소에 일을 기다리고 있다.
    • 서버에서 요청을 받으면 풀에서 사용 가능한 스레드가 작동하여 즉시 서비스된다.
    • 풀에 사용 가능한 스레드가 없으면 사용 가능한 스레드가 생길 때까지 작업이 대기된다.
    • 스레드가 서비스를 완료하면 풀로 돌아가서 작업을 기다린다.
  • 스레드 풀의 장점
    • 새 스레드를 만들어 주기보다 기존 스레드로 서비스해 주는 것이 더 빠르다.
    • 스레드 풀은 임의 시각에 존재할 스레드 개수에 제한을 둔다. 이러한 제한은 많은 수의 스레드를 병렬 처리할 수 없는 시스템에 도움이 된다.
    • 태스크를 생성하는 방법을 태스크로부터 분리하면 태스크를 실행을 다르게 할 수 있다.
      • 태스크를 일정 시간 후에 실행되도록 스케줄 하거나 혹은 주기적으로 실행시킬 수 있다.

(2) OpenMp

C, C++ 또는 FORTRAN으로 작성된 API와 컴파일러 디렉티브의 집합
  • 공유 메모리 환경에서 병렬 프로그래밍을 할 수 있도록 도움을 준다.

(3) Grand Central Dispatch

개발자가 병렬로 실행될 코드 섹션(task)을 식별할 수 있도록 하는 런타임 라이브러리, API 및 언어의 확장의 조합
  • 스레딩에 대한 대부분의 세부 사항을 관리한다.
  • GCD는 실행시간 수행을 위해 task를 디스패치 큐에 넣어서 스케줄 한다.
  • 큐에서 task를 제거할 때 관리하는 스레드 풀에서 가용 스레드를 선택하여 태스크를 할당한다.
  • GCD는 두 가지 유형의 디스패치 큐를 유지한다.
    • 직렬(Serial) : FIFO 순서대로 제거된다.
    • 병행(Concurrnet) : 한 번에 여러 태스크가 제거되어 병렬로 실행될 수 있다.

 

5. 스레드와 관련된 문제들 (Threading Issues)

(1) Fork() 및 Exec() 시스템 콜

  • 만일 한 프로그램의 스레드가 fork()를 호출한다면?
    • 새로운 프로세스는 모든 스레드를 복제해야 하는가?
    • 한 개의 스레드만 가지는 프로세스여야 하는가?
  • 몇몇 Unix 시스템에서는 두 가지 버전을 모두 지원한다.
  • Fork() & Exec()을 함께 고려한다면
    • Fork() 이후 Exec()이 호출된다면, 모든 스레드를 복제할 이유가 없다.
    • Fork() 이후 Exec()이 호출되지 않는다면, 모든 스레드의 복제가 의미가 있다.

(2) 시그널 처리 (Signal Handling)

  • 단일 스레드 프로그램에서 시그널은 프로세스 레벨에서 처리된다.
    • 시그널을 받으면, 프로세스 수행을 잠시 중단한 후, 시그널 처리기에서 해당 시그널을 처리한 후 다시 프로세스 수행을 재개한다.
  • 멀티 스레드 프로그램에서 시그널 처리는 여러 가지 경우가 가능하다.
    • 시그널이 적용될 스레드에게 전달 (특정 스레드가 시그널 처리기를 등록한 경우)
    • 모든 스레드에게 전달
    • 몇몇 스레드에게만 선택적으로 전달
    • 특적 스레드가 모든 신호를 전달받도록 지정

(3) 스레드 취소 (Thread Cancellation)

  • 스레드가 끝나기 전에 강제 종료시키는 작업
  • Example
    • 여러 스레드가 데이터베이스를 검색하다, 한 스레드가 원하는 결과를 찾았다면 나머지 스레드들은 취소된다.
    • 웹 브라우저가 페이지를 적재하는 도중 사용자가 stop 버튼을 눌렀다면 관련 스레드들이 취소된다.
    • 취소되어야 할 스레드를 목적 스레드(target thread)라고 부른다.
  • 취소의 두 가지 방식
    • 비동기식 취소 (Asynchronous cancellation)
      • 한 스레드가 즉시 목적 스레드를 강제 종료시킨다
    • 지연 취소 (Deffered cancellation) 
      • 목적 스레드가 주기적으로 자신이 강제 종료되어야 할지를 점검한다. 
  • Pthreads의 3가지 취소 모드
    • off : 취소 불가능
    • 지연 : 취소 가능
      • 기본 취소 유형
    • 비동기식 : 취소 가능
  • Pthreads는 스레드가 취소될 때 정리 핸들러 (cleanup handler)라고 하는 함수가 호출되게 할 수 있다.

(4) 스레드-로컬 저장장치 (Thread-Local Storage, TLS)

  • 특정 thread에게만 할당되는 데이터
  • 지역 변수는 하나의 함수가 호출되는 동안에만 보이지만 TLS는 전체 함수 호출에 걸쳐 보인다.
반응형

'OS(운영체제)' 카테고리의 다른 글

동기화 (Synchronization) - (2)  (0) 2021.12.09
동기화 (Synchronization) - (1)  (0) 2021.12.09
프레임 할당 (Allocation of Frames)  (0) 2021.12.09
페이지 교체 (Page Replacement)  (0) 2021.12.09
가상메모리 (Virtual memory)  (0) 2021.12.09

댓글