본문 바로가기
computer science/운영체제

[운영체제] 쓰레드란?

by 박연호의 개발 블로그 2019. 3. 2.


쓰레드 너는 누구니 ?


이전시간에 저희는 프로세스에 대해 공부하였습니다.

프로세스는 디스크에 존재하는 프로그램이 메모리에 올라가 CPU를 할당받은 실행중인 프로그램을 의미합니다. 여기서 프로세스와 같이 다니는 녀석이 있는데 바로 쓰레드 입니다. 

위키피디아에는 쓰레드를 어떤 프로그램 내에서, 특히 프로세스 내에 실행되는 흐름의 단위를 말한다 라고 정의하고 있습니다.

쓰레드는 프로세스가 CPU로 부터 할당받은 자원을 이용하는 실행의 단위입니다. 여기서 실행의 단위란 하나의 일을 하는 단위입니다.


또한 쓰레드가 생성되면 Stack영역만 할당받고 Data, Code, Heap영역을 프로세스의 자원과 공유하게 됩니다.


※ 쓰레드와 프로세스는 어떤 차이점을 가지고 있을까요?

여러개의 프로세스가 있을때 각각의 프로세스는 독립적인 메모리영역을 가집니다.

반면에 쓰레드는 다른 쓰레드와 프로세스의 Stack을 제외한 Data, Code, Heap영역을 공유합니다. 

 


위의 사진은 프로세스와 쓰레드의 관계를 가장 잘 설명해주는 사진이라고 생각합니다. 하나의 프로세스가 생성될 때, 메인 쓰레드도 같이 생성됩니다.

하나의 프로세스가 여러개의 쓰레드로 구성되어 있는데, 각각의 쓰레드는 프로세스가 하는 일의 일부를 맡아 수행합니다. 이처럼 하나의 프로세스내에서 여러개의 쓰레드를 사용하는 것을 멀티 쓰레드라고 합니다. 


근데 한가지 궁금한 점이 왜 여러개의 프로세스를 만드는 대신 쓰레드를 여러개 만드는 것일까요 ?


멀티 프로세스 vs 멀티 쓰레드


멀티 프로세스

부모-자식 관계이지만 결국에는 각각의 독립된 메모리 영역을 가집니다.

fork를 통해서 부모 프로세스를 복제합니다.

프로세스간 통신하기 위해서는 IPC(Inter Process Communication; 세마포어, 큐, 공유메모리)를 사용해야 합니다.

여러개의 프로세스 중에서 하나가 죽어도 다른 프로세스에 영향을 미치지 않는습니다.


멀티 쓰레드

하나의 프로세스가 다수개의 작업을 각각 쓰레드를 이용하여 동시에 실행할 수 있습니다.

윈도우, 리눅스 많은 운영체제들이 멀티 프로세싱을 사용하고 있지만 멀티 쓰레딩을 기본적으로 사용합니다.

멀티 쓰레드의 대표적인 예시를 웹 서버



멀티 프로세스를 사용하는 대신 멀티 쓰레드를 사용하는 이유는 다음과 같습니다.



1. 멀티 프로세스로 실행되는 작업을 멀티 쓰레드로 실행할 경우, 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있습니다.


2. 프로세스 간의 Context Switching시 단순히 CPU 레지스터 교체 뿐만 아니라 RAM과 CPU 사이의 캐쉬 메모리에 대한 데이터까지 초기화되므로 오버헤드가 크기 때문


3. 쓰레드는 프로세스 내의 메모리를 공유하기 때문에 독립적인 프로세스와 달리 쓰레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 됩니다.


멀티 쓰레드에서 주의할 점


위에서 멀티 쓰레드의 장점을 설명하였습니다. 여러개의 쓰레드가 프로세스의 자원(Code, Data, Heap)을 같이 사용하기 때문에 이 부분에 대해 적절한 제어가 필요합니다. 예를 들어서, 내가 어떤 데이터를 조작하고 있는데, 그 도중에 다른 쓰레드가 이 데이터에 대해 접근한다면 이는 데이터에 대한 일관성에 문제가 생길 것입니다. 이런 이유 때문에 여러 쓰레드가 접근하는 공유자원에 대해서는 동기화작업을 해주어야 합니다.


커널 쓰레드 vs 유저 쓰레드

커널 쓰레드와 유저 쓰레드의 가장 큰 차이점은 쓰레드의 생성 주체입니다.


커널 쓰레드


커널이 쓰레드 기능을 API형태로 제공하며, 생성된 쓰레드에 대해서 커널이 직접 관리합니다.

실행을 하는데 있어 쓰레드A,B,C는 완전히 대등하고, 우선순위도 같으며, 각각 같은 시간을 나눠 가집니다.

만약 쓰레드A가 I/O작업이 되는 경우 스케줄러는 쓰레드B,C에게 실행의 우선순위를 넘겨줍니다.


커널이 직접 쓰레드를 관리해주기 때문에 안정성과 다양한 기능을 제공하며, 하나의 쓰레드가 I/O작업을 하는 동안에도 다른 쓰레드를 사용하여 다른 작업을 진행할 수 있다. 또한 프로세스의 쓰레드들을 몇몇 프로세서에서 한꺼번에 디스패치 할 수 있기 때문에 멀티프로세서 환경에서 매우 빠르게 동작합니다.

하지만, 유저모드에서 커널모드로 전환이 빈번하게 일어나기 때문에 성능에 악영향을 미칩니다.



유저 쓰레드


사용자가 직접 쓰레드 기능을 구현하여 라이브러리 형태로 제공됩니다(커널이 제공해주지 않으니깐 내가 만들어서 쓴다 !)

여기서 커널은 단순히 프로세스만을 관리한다. 각각의 프로세스에 1/2 실행시간이 주어진다면 다시 프로세스 내부적으로 쓰레드에게 실행시간이 할당됩니다.

프로세스 A,B에 각각 1이라는 시간이 주어진다면, 프로세스A의 쓰레드A,B는 각각 1/2의 시간씩 받지만 프로세스B의 쓰레드C는 1의 시간을 가지게 됩니다.

또한 만약 쓰레드A가 I/O작업에 들어가는 경우 프로세스A는 block상태가 됩니다.


커널 쓰레드와는 다르게 모드 간의 전환이 없어 성능상의 이점을 가져오지만, 하나의 쓰레드가 I/O작업 처럼 blocking 되면 프로세스 전체가 blocking되는 문제가 생깁니다.