운영체제 (Operating Systems) (Multi-Thread Programming) 다중 스레드 프로그래밍 (Multi-Thread Programming) 문양세 강원대학교 IT대학 컴퓨터과학전공
강의 목표 스레드 개념을 이해하고, 다중 스레드 프로그래밍의 효과를 이해한다. CPU 이용의 기본 단위로서 스레드를 이해하고 학습한다. 다중 스레드 프로그래밍과 관련된 여러 이슈를 검토한다. Pthreads API 및 Win32, Java 스레드 라이브러리를 학습한다.
강의 목차 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약 다중 스레드 프로그래밍 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약
스레드(Threads)란? 프로세스 내의 제어 흐름(a flow of control within a process) 다중 스레드 프로그래밍 프로세스 내의 제어 흐름(a flow of control within a process) 제3장에서 공부한 프로세스는 단일 스레드 프로세스로 볼 수 있다. 다중 스레드 프로세스에서는 하나의 프로세스 내에 여러 제어(control)가 존재한다. 스레드는 CPU 이용의 기본 단위로서 아래 정보들로 구성된다. 스레드 ID, 프로그램 카운터, 레지스터 집합, 스택 등 동일 프로세스의 여러 스레드는 코드 영역, 데이터 영역, 운영체제 자원 (예: 열린 파일, 시그널)을 공유한다. 프로세스가 다수의 제어 스레드를 가진다면, 프로세스는 동시에 하나 이 상의 작업을 실행할 수 있다.
단일 vs 다중 스레드 프로세스 다중 스레드 프로그래밍
다중 스레드 프로그램 (1/2) 현대 운영체제의 대다수 소프트웨어 패키지는 다중 스레드를 지원한다. 다중 스레드 프로그래밍 현대 운영체제의 대다수 소프트웨어 패키지는 다중 스레드를 지원한다. 웹 브라우저의 스레드 이용 예 이미지와 텍스트를 표시(display)하는 스레드 1개 네트워크로부터 데이터를 읽어는 스레드 1개 워드 프로세서의 스레드 이용 예 그래프를 표시(display)하는 스레드 1개 사용자의 키 스트로크에 응답하는 스레드 1개 스펠링, 문법 검사를 수행하는 스레드 1개
다중 스레드 프로그램 (2/2) 웹 서버 많은 운영체제 커널들이 현재 다중 스레드 기반이다. 다중 스레드 프로그래밍 웹 서버 단일 스레드 웹 서버: 한 클라이언트 요청에 대한 서비스를 완료할 때까지 다른 클라이 언트 요청에 대한 서비스를 기다려야 한다. 다중 프로세스 웹 서버: 스레드가 일반화되기 전에 사용되었으며, 새로운 프로세스를 생 성하여 추가적인 클라이언트 요청을 처리한다. 프로세스 생성 오버헤드 발생 다중 스레드 웹 서버: 프로세스에 비해 오버헤드가 작은 스레드를 생성하여 여러 클라이 언트에 대해 동시에 서비스한다. 많은 운영체제 커널들이 현재 다중 스레드 기반이다. 여러 스레드들이 커널 내에서 동작한다. 각 스레드는 장치를 관리하거나 인터럽트를 처리하는 등 특정 작업을 수행한다.
다중 스레드화 된 서버 구조 다중 스레드 프로그래밍
다중 스레드 프로그램의 장점 반응성(responsiveness) 자원공유(resource sharing) 다중 스레드 프로그래밍 반응성(responsiveness) 상호작용 응용의 다중 스레딩은 하나의 스레드가 일시 봉쇄(blocking)되어도 다른 스레 드는 수행을 계속하게 한다. 사용자 응답성 증가 자원공유(resource sharing) 하나의 프로세스에 속한 여러 스레드는 메모리 등의 자원을 공유한다. 경제성(economy) 한 프로세스 내의 스레드는 자원을 공유하기 때문에 생성과 문맥 전환(context-switch) 을 수행함에 있어 프로세스에 비해 훨씬 경제적이다. 솔라리스의 경우, 프로세스 생성은 30배, 문맥 전환은 5배 더 경제적이다. 확장성(scalability) - 다중 프로세서 구조의 활용 다중 프로세서(다중 코어) 시스템에서 스레드는 서로 다른 프로세서(코어)에서 병렬로 실행될 수 있다.
다중 코어 프로그래밍(Multi-Core Programming) 다중 스레드 프로그래밍 다중 스레드 프로그래밍은 다중 코어를 더 효율적으로 사용할 수 있고, 병행성(parallelism)을 더 향상시킬 수 있다. 다중 코어 시스템은 운영체제 등 시스템 개발자뿐 아니라 응용 프로그램 개발자의 프로그래밍 기법 변화도 요구한다. 단일 코어 시스템에서의 병행 실행 다중 코어 시스템에서의 병행 실행
다중 코어 시스템의 효율성 극대화 이슈 다중 스레드 프로그래밍 작업 나누기(dividing activities): 응용이 여러 코어에서 병렬적으로 수행 될 수 있도록 병행 가능 태스크로 나누는 작업이 필요하다. 균형(balance): 병렬 실행이 가능한 태스크들이 가급적 균등한 기여도를 가져야 한다. 데이터 분리(data splitting): (응용을 독립 태스크로 나누는 것 처럼) 태스 크가 접근/변경하는 데이터도 개별 코어에서 수행될 수 있도록 독립적이 어야 한다. 데이터 종속성(data dependency): 태스크들이 사용하는 데이터가 종속 적 관계(예: 하나 작업한 후 다음 작업이 실행)가 없어야 한다. 시험 및 디버깅(test & debugging): 병렬 수행은 다양한 실행 경로를 만 든다. 다중 스레드 프로그램을 시험/디버깅하는 환경 등이 필요하다.
강의 목차 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약 다중 스레드 프로그래밍 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약
스레드의 두 가지 유형 사용자 스레드(user thread) vs 커널 스레드(kernel thread) 다중 스레드 프로그래밍 사용자 스레드(user thread) vs 커널 스레드(kernel thread) 사용자 스레드는 사용자 수준(user level)에서, 커널 스레드는 커널 수준 (kernel level)에서 지원된다. 운영체제 커널은 커널 수준에서 스레드를 지원하고 관리한다. 사용자 스레드는 프로그래머에게는 보이나 커널에게는 알려지지 않는 스레드이다. 일반적으로 사용자 스레드는 커널 스레드보다 더 빨리 생성하고 관리할 수 있다. 왜냐하면 커널의 개입이 필요하지 않기 때문이다.
사용자 스레드(User Threads) 스레드 관리는 사용자 레벨 스레드 라이브러리에 의해 이루어진다. 다중 스레드 프로그래밍 스레드 관리는 사용자 레벨 스레드 라이브러리에 의해 이루어진다. 사용자 스레드는 커널 위(above)에서 동작하므로, 커널의 지원 없이 관 리된다. 세 가지 기본 스레드 라이브러리 POSIX Pthreads Win32 threads Java threads
커널 스레드(Kernel Threads) 다중 스레드 프로그래밍 커널 스레드는 운영체제 커널에 의해 직업 지원받고 관리된다. 커널 스레드 예제 Windows XP/2000 Solaris Linux Tru64 UNIX Mac OS X
User- vs Kernel-Level Threads 다중 스레드 프로그래밍
다중 스레드 모델(Multithreading Models) 다중 스레드 프로그래밍 사용자 스레드들와 커널 스레드들 사이의 관계 다대일(Many-to-One) 모델 일대일(One-to-One) 모델 다대다(Many-to-Many) 모델
다대일(Many-to-One) 모델 여러 사용자 스레드들이 하나의 커널 스레드에 매핑된다. 다대일 모델 예제 다중 스레드 프로그래밍 여러 사용자 스레드들이 하나의 커널 스레드에 매핑된다. 스레드 관리는 사용자 공간의 스레드 라이브러리에 의해 이루어진다. 사용자가 원하는 만큼의 많은 사용자 스레드를 생성할 수 있으므로 효율적이다. 하나의 스레드가 봉쇄형(blocking) 시스템 호출을 할 경우, 전체 프로세스가 봉쇄된다. 한 번에 하나의 스레드만이 커널에 접근할 수 있기 때문에, 다중 스레드가 다중 프로세 서에서 돌아도 병렬로 작동할 수 없다. 다대일 모델 예제 솔라리스 스레드 라이브러리 GNU Portable 스레드
일대일(One-to-One) 모델 하나의 사용자 스레드는 하나의 커널 스레드에 매핑된다. 일대일 모델 예제 다중 스레드 프로그래밍 하나의 사용자 스레드는 하나의 커널 스레드에 매핑된다. 다대일 모델보다 더 많은 병렬성을 제공한다. 하나의 스레드가 봉쇄되더라도 다른 스레드들은 계속 수행될 수 있다. 다중 처리기(혹은 다중 코어)에서 다중 스레드가 병렬적으로 수행되도록 한다. 사용자 스레드 생성은 대응하는 커널 스레드를 생성을 필요로 한다. 오버헤드 하나의 프로세스가 생성할 수 있는 쓰레드 수는 다대일 모델보다 더 적다. 너무 많은 스레드를 생성하지 않도록 주의해야 한다. 일대일 모델 예제 Windows NT/XP/2000 Linux Solaris 9과 그 이후 버전
다대다(Many-to-Many) 모델 여러 사용자 스레드가 여러 커널 스레드와 매핑된다. 다대다 모델의 예제 다중 스레드 프로그래밍 여러 사용자 스레드가 여러 커널 스레드와 매핑된다. 정확히는 여러 사용자 스레드들이 그 보다 더 적은 수의 커널 스레드와 매핑된다. 운영체제가 충분한 수의 커널 스레드를 생성하도록 한다. 응용은 원하는 수 만큼의 사용자 스레드들을 생성하고 이들에 대응하는 커널 스레드들 이 다중 처리기에서 병렬로 수행될 수 있다. 다대일과 일대일의 장점을 취한 접근법 다대다 모델의 예제 Solaris 9 이전 버전 ThreadFiber 패키지를 가진 Windows NT/2000
다대다 모델의 변형인 두 단계 모델 - SKIP 다대다 모델의 여러 변형 중 대표적인 방법 두 단계 모델의 예제 다중 스레드 프로그래밍 다대다 모델의 여러 변형 중 대표적인 방법 다대다 모델과 기본적으로 유사함 여러 사용자 스레드들이 같은 수 혹은 그 보다 적은 수의 커널 스레드로 다중화된다. 그런데, 하나의 사용자 스레드가 하나의 커널 스레드에 종속되는 것도 허용한다. 즉, 다대다 모델을 기반으로 하되, 일대일 모델의 기능을 지원한다. 두 단계 모델의 예제 IRIX HP-UX Tru64 UNIX Solaris 8과 그 이전 버전들
스레드의 조금 복잡한 매핑 예제 다중 스레드 프로그래밍
강의 목차 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약 다중 스레드 프로그래밍 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약
스레드 라이브러리 스레드 라이브러리는 프로그래머가 스레드를 생성하고 관리할 수 있는 API를 제공한다. 다중 스레드 프로그래밍 스레드 라이브러리는 프로그래머가 스레드를 생성하고 관리할 수 있는 API를 제공한다. 스레드 라이브러리 구현의 두 가지 방법 커널의 지원 없이 사용자 공간에서 스레드 기능을 제공한다. 라이브러리를 위한 모든 코드와 데이터 구조는 사용자 공간에 존재한다. 모든 함수 호출은 커널 모드가 아닌 사용자 모드에서 실행된다. 운영체제의 지원을 받는 커널 레벨 라이브러리를 구현한다. 모든 코드와 데이터 구조는 커널 공간에 존재한다. 함수 호출은 커널의 시스템 호출을 야기한다.
주요 라이브러리 – POSIX Pthreads 다중 스레드 프로그래밍 스레드 생성/동기화에 대한 POSIX 표준(IEEE 1003.1c) API를 제공한다. 스레드 동작에 대한 API 명세를 제공할 뿐이며, 이의 구현은 각 운영체제 에 따라 다르게 구현될 수 있다. 솔라리스, Linux, Mac OS X 등 UNIX 운영체제에서 공통 지원한다. 사용자 레벨 혹은 커널 레벨 라이브러리를 제공한다. 스레드 예제 프로그램 𝒔𝒖𝒎= 𝒊=1 𝑵 𝒊
POSIX Pthreads 프로그램 예제 다중 스레드 프로그래밍
주요 라이브러리 – Win32 Threads API와 동작 절차가 기본적으로 Pthreads와 유사하다. 다중 스레드 프로그래밍 API와 동작 절차가 기본적으로 Pthreads와 유사하다.
주요 라이브러리 – Java Threads 자바 스레드는 JVM에 의해 관리된다. 다중 스레드 프로그래밍 자바 스레드는 JVM에 의해 관리된다. 전형적으로 JVM이 구동되는 운영체제에 의해 스레드 모델이 구현된다. 즉, 운영체제에 따라 스레드 모델이 달리 구현된다. 자바 스레드는 다음 두 방법에 의해 생성될 수 있다. Thread class를 상속(extends)한다. Runnable interface를 구현(implements)한다. 보다 보편적으로 사용된다.
Java 스레드 예제 다중 스레드 프로그래밍
강의 목차 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약 다중 스레드 프로그래밍 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약
스레드 관련 주요 이슈 fork()와 exec() 시스템 호출 스레드 취소(cancellation) 다중 스레드 프로그래밍 fork()와 exec() 시스템 호출 스레드 취소(cancellation) 시그널 처리(signal handling) 스레드 풀(thread pools) 스레드별 데이터(thread-specific data) 스케줄러 활성화(scheduler activation)
fork() & exec() 시스템 호출 다중 스레드 프로그래밍 다중 스레드 프로그램에서 프로세스를 복제/생성하는 fork() 시스템 호출 을 실행한다면? 새로운 프로세스는 모든 스레드를 복제해야 하는가? 아니면 한 개의 메인 스레드만 가지는 프로세스여야 하는가? 몇몇 Unix 시스템에서는 두 가지 버전을 모두 지원한다. exec() 시스템 호출은 어떠한가? 기존 스레드들을 모두 무시하고, 새로운 프로그램으로 대체된다. fork() & exec()를 함께 고려한다면, fork() 이후 exec()가 호출된다면, 모든 스레드를 복제할 이유가 없다. fork() 이후 exec()가 호출되지 않는다면, 모든 스레드의 복제가 의미가 있다.
스레드 취소(Thread Cancellation) (1/2) 다중 스레드 프로그래밍 스레드가 끝나기 전에 다른 스레드에 의해 종료되는 것을 의미한다. 예제1: 여러 스레드가 데이터베이스를 검색하다, 한 스레드가 원하는 결과를 찾았다면 나머지 스레드들은 취소된다. 예제2: 웹 브라우저가 페이지를 적재(loading)하는 도중에 사용자가 stop 버튼을 눌렀다 면 관련 스레드들이 취소된다. 취소되어야 할 스레드를 목적 스레드(target thread)라 부르며, 이를 취소 하는 두 가지 방법이 있다. 비동기 취소(asynchronous cancellation): 한 스레드가 즉시 목적 스레드를 강제로 종료 시킨다. 지연 취소(deferred cancellation): 목적 스레드는 주기적으로 자신이 강제 종료가 되어 야 할지 점검한다. 자발적 종료이므로 목적 스레드가 질서 정연하게 종료될 수 있는 기회가 주어진다.
스레드 취소(Thread Cancellation) (2/2) 다중 스레드 프로그래밍 스레드 취소가 어려운 점은 취소 스레드들에 할당된 자원 문제이다. 비동기 취소(asynchronous cancellation) 상황에 따라 할당된 자원을 모두 회수할 수도, 그렇지 못할 수도 있다. 자원이 회수되지 않으면 이후 시스템 자원을 모두 활용치 못하는 문제가 발생한다. 지연 취소(deferred cancellation) 취소하고자 하는 스레드는 목적 스레드가 취소 예정이라 표시(플래그)한다. 목적 스레드는 플래그를 보고 자원을 반환한 후 안전하게 취소할 수 있다.
시그널 처리(Signal Handling) (1/2) 다중 스레드 프로그래밍 시그널(signal)은 Unix에서 프로세스에게 어떤 사건이 일어났음을 알리 기 위해 사용된다. 시그널의 두 가지 유형 동기식 시그널(synchronous signal): 어떤 사건을 처리하기 위해 발생한다. (예: 불법적인 메모리 접근, 0으로 나누기) 비동기식 시스널(asynchronous signal): 임의 시점에 발생한다. (예: 인터럽트(cntl-C), 타이머 만료) 동기식이든 비동기식이든 시그널은 다음과 같이 전달된다. 시그널은 특정 사건이 일어나야 생성된다. 시그널이 생성되면 프로세스에게 전달된다. 시그널이 전달되면 반드시 처리(handling)되어야 한다.
시그널 처리(Signal Handling) (2/2) 다중 스레드 프로그래밍 모든 시그널은 둘 중 하나의 처리기(handler)에 의해 처리된다. 디폴트 시그널 처리기: 시그널마다 기본적인 처리 방법을 정의해 놓는다. 사용자 정의 시그널 처리기: 사용자가 시그널 처리 방법을 정의할 수 있다. 단일 스레드 프로그램에서 시그널은 프로세스 레벨에서 처리된다. 시그널을 받으면, 프로세스 수행을 잠시 중단한 후, 시그널 처리기에서 해당 시그널을 처리한 후 다시 프로세스 수행을 재개한다. 다중 스레드 프로그램에서 시그널 처리는 다소 복잡하며, 다음의 선택이 가능하다. 시그널이 적용될 스레드에게 전달한다. (어떤 스레드가 시그널 처리기를 등록한 경우) 모든 스레드에 전달한다. 몇몇 스레드에게만 선택적으로 전달한다. 특정 스레드가 모든 신호를 전달받도록 지정한다.
스레드 풀(Thread Pools) 다중 스레드 프로그래밍 필요할 때 마다 새롭게 스레드를 생성하는 것은 큰 오버헤드이다. 이를 해결하는 한 옵션이 스레드 풀의 사용이다. 스레드 풀: 작업을 기다르는 스레드들의 집합 프로세스는 시작 시에 일정 수의 스레드를 생성하여 스레드 풀에 놓는다. 요청을 받으면, 서버는 풀로부터 스레드를 깨워서 요청을 서비스에게 전달한다. 스레드가 서비스를 끝내면, 다시 풀로 반환되고 다음 작업을 기다린다. 만약 풀에 더 이상 가용 스레드가 없다면, 서버는 가용 스레드가 생길 때까지 기다린다. 스레드 풀의 장점 일반적으로, 이미 존재하는 스레드에 요청하는 것이 새로운 쓰레드를 생성하는 것보다 서비스를 더 빨리 받을 수 있다. 응용 프로그램에서 스레드의 수는 풀의 사이즈에 종속되게 한다. 프로세서 개수, 성능에 따라 스레드 수를 제한함으로서 효율성을 높을 수 있다.
스레드별 데이터(Thread-Specific Data) 다중 스레드 프로그래밍 프로세스에 속한 스레드들은 서로 데이터를 공유한다. 어떤 상황에서, 각 스레드는 자신만의 데이터가 필요할 수도 있다! 각 스레드가 자기 자신만의 데이터 영역을 갖도록 하는 방법이다. 예: 트랜잭션 처리 시스템에서 각 스레드는 독립된 트랜잭션을 수행한다. 대부분의 스레드 라이브러리(Win32, Pthreads, Java)는 스레드 별 데이터를 지원하는 방법을 제공한다.
강의 목차 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약 다중 스레드 프로그래밍 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약
Windows XP 스레드 기본적으로 일대일 매핑으로 구현된다. 각 스레드가 포함하는 정보 다중 스레드 프로그래밍 기본적으로 일대일 매핑으로 구현된다. fiber 라이브러리를 사용하면 다대다 기능도 제공한다. 각 스레드가 포함하는 정보 각 스레드를 유일하게 식별하는 스레드 ID 처리기의 상태를 나타내는 레지스터 집합 사용자 모드 실행을 위한 사용자 스택, 커널 모드 실행을 위한 커널 스택 개인 데이터 저장 영역 스레드의 기본 데이터 구조가 포함하는 정보 ETHREAD: 실행 스레드 블록(executive thread block) KTHREAD: 커널 쓰레드 블록(kernel thread block) TEB: 스레드 환경 블록(thread environment block) 스레드의 문맥(context)
Windows XP 스레드의 자료 구조 다중 스레드 프로그래밍
리눅스 스레드(Linux Threads) 다중 스레드 프로그래밍 리눅스는 스레드(threads)라기 보다는 태스크(tasks)으로 간주한다. 사실 리눅스는 프로세스와 스레드를 구분하지 않는다. 스레드 생성은 clone() 시스템 호출에 의해 이루어진다 clone()은 자식 태스크가 부모 태스크(프로세스)와 주소 공간을 공유하는 것을 가능케 한다. 공유 정도는 플래그에 의해 제어된다.
강의 목차 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약 다중 스레드 프로그래밍 스레드 개요 다중 스레드 모델 스레드 라이브러리 스레드 관련 이슈 스레드 지원 운영체제 사례 요약
요약(1/2) 스레드는 프로세스 내의 제어 흐름이다. 다중 스레딩(multithreading)의 장점 다중 스레드 프로그래밍 스레드는 프로세스 내의 제어 흐름이다. 다중 스레드 프로세스는 같은 주소 공간 내에 여러 다른 제어 흐름을 포함한다. 다중 스레딩(multithreading)의 장점 향상된 반응성, 프로세스 내의 자원 공유 경제성, 다중 프로세서 구조를 이용한 확장성 사용자 레벨 스레드는 프로그래머에게는 보이고, 커널에게는 알려지지 않은 스레드이다. 운영체제 커널은 커널 레벨 스레드를 지원하고 관리한다.
요약(2/2) 사용자 스레드와 커널 스레드 관계의 세 가지 모델 다중 스레드 프로그래밍 사용자 스레드와 커널 스레드 관계의 세 가지 모델 일대일(one-to-one) 모델 다대일(many-to-one) 모델 다대다(many-to-many) 모델 (변형: 두 단계 모델) 스레드 라이브러리는 응용 프로그래머에게 스레드를 생성하고 관리하는 API를 제공한다. POSIX Pthreads, Win32 스레드, Java 스레드 다중 스레드 프로그램의 주요 고려사항 fork()와 exec() 시스템 호출 스레드 취소(cancellation) 시그널 처리(signal handling) 스레드 풀(thread pools) 스레드별 데이터(thread-specific data)