CPU 수행의 기본 단위
/가장 작은 실행 단위
또는 프로세스 안의 제어권의 흐름
하나의 프로세스는 하나 이상의 쓰레드를 가질 수 있으며, 각 쓰레드는 프로세스의 자원을 공유한다. (메모리 공간, 파일 핸들 등)
쓰레드 간에는 힙 메모리 영역을 공유하지만, 스택 메모리는 각각 독립적으로 가진다.
프로세스를 여러 개 수행해도 되지만 쓰레드를 사용하는 이유는 다음과 같다.
- 프로세스를 생성하거나 Context Switching 하는 작업은 너무 무겁고 잦으면 성능 저하가 발생하는데, 쓰레드를 생성하거나 Switching하는 것은 그에 비해 가볍다.
- 두 프로세스가 하나의 데이터를 공유하려면 메시지 패싱이나 공유 메모리 또는 파이프를 사용해야해서 번거롭다.
한 프로세스가 하나의 쓰레드를 이용하여 한 번에 한 작업만 수행하는 것은
싱글 쓰레드
한 프로세스가 여러 쓰레드로 동시에 여러 작업을 수행하는 것은멀티 쓰레드
프로세스 내의 쓰레드는 모두 각각 독립적인 실행 파일이며, 모든 쓰레드는 프로세스의 일부이다.
프로세서가 여러 개인 경우 멀티 쓰레드를 통해
병렬성
을 높일 수 있다.
프로세서가 하나인 경우 멀티 쓰레드를 통해동시성
을 높일 수 있다.
실제로는 각각의 시간에 한 작업만 수행되지만, 병렬적으로 수행되는 것처럼 보인다.
만약, 한 쓰레드가 blocked(waiting)되더라도 커널이 다른 쓰레드로 switch시켜 실행할 수 있어서, 빠른 처리가 가능하다.
1. 응답성
싱글 쓰레드인 경우, 작업이 끝나기 전까지 사용자에게 응답하지 않는다. 반면, 멀티 쓰레드인 경우, 작업을 분리해서 수행하므로 실시간으로 사용자에게 응답할 수 있다. ex) 하나의 쓰레드가 이미지 파일을 로드하고 있는 동안, 다른 쓰레드에서 사용자와 상호작용 가능
2. 자원 공유
프로세스는 오직 공유 메모리나 메시지 패싱을 이용해서 자원을 공유할 수 있지만, 쓰레드는 자신이 속한 프로세스 내의 쓰레드들과 메모리나 자원을 공유하여 효율적으로 사용할 수 있다.
3. 경제성
프로세스를 새로 생성하는 비용보다 쓰레드를 새로 생성하는 게 훨씬 싸다. 그리고 Context Switching의 오버헤드 또한 쓰레드가 더 경제적이다. Solaris에선 쓰레드 생성, switching이 각각 30배, 5배 느리다고 한다.
4. 확장성
싱글 쓰레드인 경우 한 프로세스는 오직 한 프로세서에서만 수행 가능하다. 반면, 멀티 쓰레드인 경우 한 프로세스를 여러 프로세서에서 수행할 수 있어서 효율적이다.
1. 임계 영역
둘 이상의 쓰레드가 동시에 실행하면 문제를 일으키는 코드 블록이다. 공유하는 자원에 동시에 접근하는 경우, 프로세스와 달리 쓰레드는 데이터와 힙 영역을 공유하기 때문에 어떤 쓰레드가 다른 쓰레드에서 사용 중인 변수나 자료구조에 접근하여 이상한 값을 읽어오거나 수정할 수 있다.
따라서, 동기화가 필요하다.2. 동기화
동기화를 통해 쓰레드의 작업 처리 순서와 공유 자원에 대한 접근을 컨트롤할 수 있다.
(Java의 synchronized)그러나, 불필요한 부분까지 동기화를 하는 경우, 과도한 lock으로 인해 병목 현상을 발생시켜 성능이 저하될 가능성이 높다.
동기화 방법에는 뮤텍스와 세마포어가 있다.3. 오버헤드
context switching, 동기화 등의 이유 때문에 싱글 코어 멀티 쓰레딩은 쓰레드 생성 시간이 오히려 오버헤드로 작용해 단일 쓰레드보다 느려진다.