일상기록
Java - 스레드(thread) 본문
스레드(thread)란
스레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미
모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행한다.
또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 한다.
스레드를 가벼운 프로세스, 즉 경량 프로세스(LWP, light-weight process)라고 부르기도 한다.
프로세스 내에서 실행되는 흐름의 단위를 의미
멀티태스킹과 멀티스레딩
우리가 사용하는 윈도우, 유닉스를 포함한 대부분의 OS는 멀티태스킹(multi-tasking, 다중작업)을 지원하기 때문에 여러 개의 프로세스가 동시에 실행될 수 있다. 멀티스레딩은 하나의 프로세스 내에서 여러 스레드가 동시에 작업을 수행하는것이다. CPU의 코어(core)가 한 번에 단 하나의 작업만 수행할 수 있으므로, 실제로 동시에 처리되는 작업의 개수는 코어의 개수와 일치한다. 그러나 처리해야하는 스레드의 수는 언제나 코어의 개수보다 훨씬 많기 때문에 각 코어가 아주 짧은 시간 동안 여러 작업을 번갈아 가며 수행함으로써 여러 작업들이 모두 동시에 수행되는 것처럼 보이게 된다.
프로세스의 성능이 단순히 스레드의 개수에 비례하는 것은 아니며, 하나의 스레드를 가진 프로세스 보다 두 개의 스레드를 가진 프로세스가 오히려 더 낮은 성능을 보일 수도 있다.
멀티쓰레딩의 장단점
도스(DOS)와 같이 한 번에 한 가지 작업만 할 수 있는 OS와 윈도우와 같은 멀티태스킹이 가능한 OS의 차이는 이미 경험으로 잘 알고 있을 것이다. 싱글스레드 프로그램과 멀티스레드 프로그램의 차이도 이와 같다고 생각하면 된다.
멀티스레딩 장점
- CPU의 사용률을 향상시킨다.
- 자원을 보다 효율적으로 사용할 수 있다.
- 사용자에 대한 응답성이 향상된다.
- 작업이 분리되어 코드가 간결해진다.
- 스레드는 하나의 프로세스 내의 자원(코드, 데이터, 힙)을 공유하기 때문에 프로세스에 비해 자원 할당 비용이 적게 들고 문맥 교환(Context Swtich) 비용도 적게 든다.
- 다중 스레드의 경우 일부 스레드의 처리가 지연되더라도 다른 스레드에서 작업을 계속 처리할 수 있음
- 프로세스 간의 통신은 IPC가 필요한 반면, 스레드는 공유(데이터, 힙) 주소 공간을 사용하여 데이터를 교환할 수 있음
- 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리
메신저로 채팅하면서 파일을 다운로드 받거나 음성대화를 나누는 것이 가능한게 바로 멀티스레드로 작성되어 있기 때문이다. 만일 싱글스레드로 작성되어 있다면 파일을 다운로드 받는 동안에 다른 일(채팅)을 전혀 할 수 없을 것이다.
여러 사용자에게 서비스를 제공하는 서버 프로그램일 경우 멀티스레드로 작성하는 것은 필수적이다. 하나의 서버 프로세스가 여러 개의 스레드를 생성해서 스레드와 사용자의 요청이 1:1로 처리되도록 프로그래밍 해야한다.
만일 싱글스레드로 서버 프로그램을 작성한다면 사용자의 요청 마다 새로운 프로세스를 생성해야하는데 프로세스를 생성하는 것은 스레드를 생성하는 것에 비해 더 많은 시간과 메모리 공간이 필요하기 때문에 많은 수의 사용자 요청을 서비스하기 어렵다.
멀티스레딩의 단점
- 여러 스레드가 같은 프로세스 내에서 자원을 공유하면서 작업하기 때문에 발생하는 문제가 있다.
- 동기화(synchronization), 교착상태(deadlock) 같은 문제들을 고려해서 프로그래밍해야 한다.
- 하나의 스레드에 문제가 발생하면 프로세스 전체가 영향을 받는다.
- 주의 깊은 설계가 필요하며 디버깅이 까다로움 (프로그래머의 역량)
스레드의 유형
스레드는 크게 커널 영역과 사용자 영역으로 구분되는데, 이 중 멀티 스레드를 어느 영역에서 구현했느냐에 따라 사용자 수준 스레드와 커널 수준 스레드로 구분할 수 있습니다.
1. 커널 수준 스레드(1 : 1 매핑 방식)
스레드를 OS(커널)이 직접 관리(스레드 생성, 스케줄링 등등)한다.
장점
- 커널이 각 스레드를 개별적으로 관리
- 프로세스 내 스레드들이 병행 수행 가능
- 하나의 스레드가 block 되어도 다른 스레드는 계속 작업 가능
단점
- 커널 영역에서 스레드의 생성 및 관리
- 문맥 교환으로 인한 오버헤드가 큼
- 사용자 스레드보다 생성 및 관리 속도가 느림
2. 사용자 수준 스레드(N : 1 매핑)
사용자 영역의 스레드 라이브러리로 구현하며, 라이브러리는 스레드의 생성, 스케줄링 담당한다 또한 커널은 스레드의 존재를 인식하지 못하기 때문에 커널의 개입을 받지 않는다.
장점
- 커널의 개입을 받지 않아 스레드의 생성 및 관리의 부하가 적음
- 동일한 메모리 영역에서 스레드가 생성 및 관리되므로 속도가 빠름
- 라이브러리를 통한 이식성이 높음
단점
- 커널은 프로세스 단위로 자원을 할당하기 때문에 하나의 스레드가 block 될 시 모든 스레드가 대기해야 함
(커널이 프로세스의 내부 스레드를 인식하지 못하여 해당 프로세스를 대기상태로 전환시키기 때문)
3. 혼합 스레드(N : M 매핑 방식)
사용자 수준 스레드와 커널 수준 스레드를 혼합한 구조 일-대-일 방식과 다-대-일 방식의 문제점을 해결하기 위해 고안되었다.
장점
- 프로세스 내 스레드들이 병행 수행 가능
- 사용자는 원하는 수만큼 스레드 사용
- 효율적이면서도 유연함
- 스레드 풀링 기법을 통해 일대일 스레드 매핑에서의 오버헤드를 줄여줌
스레드 풀링?
시스템이 관리하는 스레드의 풀을 응용프로그램에 제공하여 스레드를 효율적으로 사용할 수 있게 하는 방법.
미리 생성한 스레드를 재사용하도록 하여 스레드 생성 시간을 줄이고 시스템 부하를 덜어준다. 그리고 동시에 생성할 수 있는 스레드수를 제한하여 시스템의 자원 소비를 줄이고 해당 응용프로그램의 성능을 일정 수준으로 유지할 수 있다.
'Java' 카테고리의 다른 글
가비지 컬렉션(Garbage Collection) (0) | 2023.04.22 |
---|---|
Java - 스트림(Stream) 만들기 (0) | 2023.04.19 |
Java - 스트림(stream) (0) | 2023.04.19 |
Java - 메소드 참조 (0) | 2023.04.19 |
Java - Function의 합성, Predicate의 결합 (0) | 2023.04.19 |