- 경량화 된 프로세스 (a lightweight process)
- 가장 작은 CPU 점유 단위
- 쓰레드는 프로세스 내부에서 thread ID, program Counter, register Set 그리고 stack 으로 구성된다.
프로세스 하나로 처리 할 때와 프로세스 내부 여러개의 쓰레드로 처리 할 때를 비교해보자.
- 빠른 응답 처리
- 새로운 요청이 들어오면 프로세스 단위에서 처리하지 않고, 프로세스 내부에서 새로운 쓰레드를 생성하고, 새로운 요청을 받을 수 있어서(Non-Blocking) 계속해서 실행 할 수 있다.
- 자원 공유
- 프로세스 내부 쓰레드에서는 데이터영역을 공유하기 때문에, 따로 shared-memory 나 message-passing 을 구현하지 않아도 된다.
- 경제적이다.
- 프로세스를 하나를 새로 만드는 것 보다, 프로세스 내부 쓰레드를 생성하는 것이 효율적
- PCB를 옮기는 컨텍스트 스위칭보다 쓰레드 컨텍스트 스위칭이 더 효율적
- 확장성이 좋다.
- 멀티 쓰레드를 통해 병렬 처리도 가능하다.
- 싱글 코어 : 쓰레드는
시분할
되어 실행 된다. - 멀티 코어 : 쓰레드가
병렬적으로
실행된다. - 프로그래밍 적인 문제
- 멀티코어, 즉 각 코어에 데이터를 분할해야하는데
어떤 기준으로 데이터를 분할 해야 할 지
고려해야한다. - 데이터 동기화, 의존성, 수행적 측면에서의 밸런스 유지 등을 고려해야 한다.
- 테스팅 , 디버깅의 어려움 (각 쓰레드가 서로가 어떤 작업을 하고 있는지 모르므로 )
- 멀티코어, 즉 각 코어에 데이터를 분할해야하는데
- 데이터 병렬
- 데이터를 기준으로 여러개의 코어에 분할한다.
- 작업 병렬
- 데이터는 분할 하지 않고, 작업 단위로 코어에 분할한다.
1. 유저 쓰레드 (User Threads)
- 사용자 모드 ( User space ) 에서 사용하는 쓰레드
- 커널 support 없이 커널 위에서 쓰레딩
2. 커널 쓰레드 (Kernel Threads)
- 커널 모드 ( Kernel space)
- 코어에서 운영체제가 직접 관리하는 쓰레드
- 다대일 모델 : 많은 유저 쓰레드에 하나의 커널 쓰레드 맵핑
- 일대일 모델 : 하나의 유저 쓰레드에 하나의 커널 쓰레드 맵핑
- 다대다 모델 : 많은 유저 쓰레드에 많은 커널 쓰레드 맵핑
쓰레드를 만들고, 관리하는 API
- POSIX Pthreads
- Windows thread
- Java Thread ( 운영체제 종속적)
위의 라이브러리는 프로그래머가 직접 쓰레드를 관리해주는 Explicit Threading 방식이었다. 그에 반해 implicit threading 이란, 프로그래머가 직접 쓰레드를 생산, 관리하는 것이 아니라 운영체제에게 쓰레드 생산, 관리를 맡기는 것이다.
-
Thread Pool
- 여러개의 쓰레드를 풀에 생성해 놓고, 필요 할 때 사용하는 방법
-
Fork & Join
- 메인 쓰레드가 여러개의 자식 쓰레드들을 만들고 (Fork) 자식 쓰레드들이 일을 마치고 다시 합쳐지는 (join) 방법
-
Open MP
- 컴파일 지시어를 사용해서 C/C++ 에서 병렬처리를 지원하는 방법
- 병렬적으로 처리할 코드 블록에
컴파일러 지시문
을 삽입하면, 해당 지시문이 지정된 코드 블록에 Open MP 라이브러리를 실행한다.
-
GCD (Grand Central Dispatch)
- MAC OS와 IOS에서 사용하는 방식으로 병렬로 처리할 블록을 지정하고, 병렬하게 처리할 수 있는 dispatch queue에 할당시켜 병렬적으로 사용하는 방법
자바스크립트는 싱글 쓰레드 언어이지만, 비동기적으로 구현된 이벤트 루프 덕분에 멀티 쓰레드 처럼 동작한다.
그렇다면 왜 자바스크립트
는 싱글 쓰레드
로 구현된걸까? 여러 이유가 있겠지만, 프론트엔드 개발자 관점에서 간단히 살펴보면 아래와 같다.
비동기 함수는 일반적으로 파라미터를 통해서 콜백을 받고, 비동기 함수가 호출된 후 즉시 다음 줄 실행이 계속된다. 콜백은 비동기 작업이 완료되고 호출 스택이 비어 있을 때만 호출된다. 따라서 웹 서버에서 데이터를 로드하거나 데이터베이스를 쿼리하는 등의 무거운 작업을 비동기식으로 수행하여, 메인 스레드가 긴 작업을 완료할 때까지 블로킹하지 않고 다른 작업을 계속할 수 있다. 만약 동기적으로 구현되어 메인 스레드가 긴 작업을 완료할 때 까지 블록킹이 된다면 브라우저의 UI가 중지되는 문제가 발생 할 수 있다.
서버 측 프로그래밍과 달리 프론트엔드에서는 사용자 이벤트의 순서
를 보장해야한다. 아래의 예시를 보자
- 사용자가 Input 란에 텍스트를 입력한다.
- 폼을 제출하면 Input 란에 입력된 텍스트를 검증한다.
- 입력된 텍스트가 n자 이상이면 alert를 띄워준다.
- 위와 같은 일련의 클라이언트 처리 과정을 순서대로 보장해줘야 한다. 만약 멀티 쓰레드로 구현이 되어있어서 Input 텍스트 입력받는 쓰레드, 폼을 제출 했을 때 텍스트를 검증하는 쓰레드, alert 띄워주는 쓰레드가 각각 동시에 실행된다면
Input 에 텍스트를 입력했더니 특정 alert를 받았다
라는 이벤트 처리 과정을 보장하지 못한다.