싱글스레드(Single thread) vs 멀티스레드 (Multi thread)

조 은길·2021년 6월 28일
65
post-thumbnail

스레드이란?? ( thread )

  • 프로세스가 할당받은 자원을 이용하는 실행의 단위

  • 한 프로세스 내에서 동작되는 여러 실행 흐름으로 프로세스 내의 Heap, Data, Code 영역을 공유 ( 멀티 스레드의 경우, 이 프로세스의 영역들을 공유한다 )

  • 하나의 프로세스를 안에서 다양한 작업을 담당하는 최소 실행 단위를 스레드라고 한다.
    ex) 크롬 브라우저(=프로세스)에서 벨로그 작성하기(=스레드1) & 유튜브로 음악 듣기(=스레드2)

  • 멀티 스레딩의 경우, 스레드 간의 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 수행 능력을 향상시킨다.

  • 각각의 스레드는 독립적인 작업을 수행해야 하기 때문에 고유한 스레드 ID, 프로그램 카운터, 레지스터 집합, 스택을 가지고 있다.


그럼 싱글 스레드와 멀티 스레드는 무엇일까??

일단, 시작에 앞서 이해를 돕기 위해 이 그림을 봐주길 바란다.

=> 싱글 스레드와 멀티 스레드의 차이는 이 그림을 통해서 가장 확실하게 보일 것같다.
그런데, 상식적으로 생각해보면, 하나 보다는 여러 스레드로 작업하는 게 더 좋지 않을까??
나도 그렇게 생각한다. 그러나, 현실은 그렇게 간단하지 않다. 모든 기술들에는 각각의 기회비용이 존재하고, 싱글 스레드와 멀티 스레드 역시 각각의 장점에 맞는 기회비용들이 존재한다. 우리는 지금부터 그것들이 무엇인지를 파악해보는 시간을 갖도록 하자!

멀티 스레드 (Multi thread)

멀티 스레드는 CPU의 최대 활용을 위해 프로그램의 둘 이상을 동시에 실행하는 기술이다.

이러한 작업은 컨텍스트 스위칭( Context Switching )을 통해서 이뤄진다. 위의 이미지에서 하나의 스레드에서 다음 스레드로 이동을 하면서, 컨텍스트 스위칭이 일어난다. 그리고, 스위칭이 일어나면서 부분적으로 조금씩 조금씩 각각의 스레드에 대한 작업을 끝내게 된다.

=> 다시 말해서, context switching이 엄청 빠르게 일어나면서, 유저(=User)의 시선에서는 프로그램들이 동시에 수행되는 것처럼 보인다.

👏멀티 스레드의 장점

  1. 응답성 : 프로그램의 일부분(스레드 중 하나)이 중단되거나 긴 작업을 수행하더라도 프로그램의 수행이 계속 되어 사용자에 대한 응답성이 증가한다. 다시 말해서, 멀티 스레드 모델은 에러 발생 시 새로운 스레드를 생성하여 극복한다. 다만, 새로운 스레드 생성이나 놀고 있는 스레드 처리에 비용이 발생한다. ( 싱글 스레드는 프로그램 일부분이 중단되거나, 에러가 발생하면 프로그램이 멈춘다 )

ex) 멀티 스레드가 적용된 웹 브라우저 프로그램에서 하나의 스레드가 이미지 파일을 로드하고 있는 동안, 다른 스레드에서 사용자와 상호작용 가능

  1. 경제성 : 프로세스 내 자원들과 메모리를 공유하기 때문에 메모리 공간과 시스템 자원 소모가 줄어든다. 스레드 간 통신이 필요한 경우에도 쉽게 데이터를 주고 받을 수 있으며, 프로세스의 context switching과 달리 스레드 간의 context switching은 캐시 메모리를 비울 필요가 없기 때문에 더 빠르다.

  2. 멀티프로세서의 활용 : 다중 CPU 구조에서는 각각의 스레드가 다른 프로세서에서 병렬로 수행될 수 있으므로 병렬성이 증가한다.

⚠️멀티 스레드의 단점

  1. context switching, 동기화 등의 이유 때문에 싱글 코어 멀티 스레딩은 스레드 생성 시간이 오히려 오버헤드로 작용해 단일 스레드보다 느리다.

  2. 공유하는 자원에 동시에 접근하는 경우, 프로세스와는 달리 스레드는 데이터와 힙 영역을 공유하기 때문에 어떤 스레드가 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다. 따라서 동기화가 필요!

  3. 멀티 스레딩을 위해서는 운영체제의 지원이 필요하다.

  4. 멀티 스레드 모델은 프로그래밍 난이도가 높다. 또한, 스레드 수만큼 자원을 많이 사용한다. 초보자의 경우, 동일한 프로그램을 만든다면, 싱글 스레드로는 완성이라도 한다. 그러나, 멀티 스레드의 경우는 완성도 못하는 경우도 많다.


싱글스레드(Single thread)

하나의 프로세스에서 오직 하나의 스레드로만 실행한다. 그렇기 때문에, 하나의 레지스터와 스택으로 표현이 가능하다.

👏싱글 스레드의 장점

  1. 문맥 교환(context switch) 작업을 요구하지 않는다.

=> 문맥 교환은 여러 개의 프로세스가 하나의 프로세서를 공유할 때 발생하는 작업으로 많은 비용을 필요로 한다.

  1. 자원 접근에 대한 동기화를 신경쓰지 않아도 된다.

=> 여러 개의 스레드가 프로세스의 자원을 공유할 경우, 각 스레드가 원하는 결과를 얻게 하려면 공용 자원에 대한 접근을 제어해야 한다. 쉽게 말해서, 모든 스레드가 일정 자원에 동시에 접근하거나, 똑같은 작업을 실행하려는 경우, 에러가 발생하거나 원하는 값이 나오지 않는다. 그래서, 스레드들이 동시에 같은 자원에 접근하지 못하도록 제어해줘야만 한다. 이 작업은 프로그래머에게 많은 노력을 요구하고 비용을 발생시킨다.

  1. 단순히 CPU만을 사용하는 계산작업이라면, 오히려 멀티스레드보다 싱글스레드로 프로그래밍하는 것이 더 효율적이다.

=> a) 두 개의 작업을 하나의 스레드로 처리하는 경우 VS b) 두 개의 스레드로 처리하는 경우

b의 경우는 짧은 시간 동안 2개의 스레드가 번갈아가면서 작업을 수행한다. 그래서 동시에 두 작업이 처리되는 것과 같이 느끼게 된다.
하지만, 오히여 두 개의 스레드로 작업한 시간이 싱글스레드로 작업한 시간보다 더 걸릴 수도 있는데, 그 이유는 스레드 간의 작업전환(context switching)에 시간이 걸리기 때문이다.

다시 말해서, 단순히 CPU만을 사용하는 작업은 싱글 스레드가 멀티 스레드보다 빠르다.

  1. 프로그래밍 난이도가 쉽고, CPU, 메모리를 적게 사용한다. (코스트가 적게든다)

반면에, 멀티 스레드 모델은 프로그래밍 난이도가 높다. 또한, 스레드 수만큼 자원을 많이 사용한다.

⚠️싱글 스레드의 단점

  1. 여러 개의 CPU를 활용하지 못한다.

프로세서를 최대한 활용하게 하려면 cluster 모듈을 사용하거나 외부에서 여러 개의 프로그램 인스턴스를 실행시키는 방법을 사용해야 한다. 이 때 고려해야할 문제가 있는데, 바로 다수의 프로그램 인스턴스가 어떻게 상태를 공유할 것인가에 대한 문제다.
(사실 이것은 멀티 스레드 환경의 서버 프로그램도 확장성을 확보하기 위해 풀어야 할 숙제이긴 하다.)

단순하고 빠른 메모리 기반 NoSQL 데이터 베이스인 Redist가 좋은 고려대상이다.

하지만 서버 프로그램 인스턴스 간 상태 공유를 최소화하거나 가능하면 없애는 방향으로 아키텍처를 설계하는 것이 가장 바람직한 방법이라고 한다.

  1. 연산량이 많은 작업을 하는 경우, 그 작업이 완료되어야 다른 작업을 수행할 수 있다.

예를 들어, 웹 게임에서 좌표를 계산하는데 3초가 걸리고 계산된 좌표를 받아 DOM에 반영한다고 생각해봅시다. 좌표를 계산하느라 3초간 DOM 업데이트 등의 다른 작업들을 수행할 수가 없습니다. 사용자 입장에서는 3초간 멍하니 기다릴 뿐입니다. 좌표를 동시에 여러 번 계산해야 하는 경우 더 심각해집니다. 좌표를 20번 계산하면 3 * 20 = 60초를 기다려야 하는 셈입니다.
3초의 시간은 어쩔 수 없다 치더라도, 계산하는 동안 UI 클릭같은 다른 작업은 진행할 수 있어야 원활한 서비스를 제공할 수 있습니다. 이럴 때는 멀티 스레드가 필요해지는 순간입니다.

  1. 싱글 스레드 모델은 에러 처리를 못하는 경우 멈춘다.

멀티 스레드 모델은 에러 발생 시 새로운 스레드를 생성하여 극복한다. 다만, 새로운 스레드 생성이나 놀고 있는 스레드 처리에 비용이 발생한다.


Node.js는 싱글 스레드인가??

일단, C++는 멀티 스레드이다.

그리고 자바스크립트는 싱글 스레드(Single thread) 언어라고 알려져 있다.

그렇다면, 자바스크립트가 실행 되는 환경(=런타임)인 Node.js도 싱글 스레드일까??

정확하게 말하면, node는 싱글스레드가 아니다. node도 여러개의 스레드를 가지고 있다. 그러나 자바스크립트를 실행하는 스레드는 단 하나이므로 node를 싱글스레드 라고 한다. 그리고 그 싱글스레드가 바로 이벤트 루프이다.

node는 이벤트 기반의 플랫폼이기 때문에 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식으로 작동한다. 이 말은 곧 node 에서 일어나는 모든 처리는 일련의 콜백을 처리하는 것과 같다고 할 수 있다. Nods.js는 v8이라는 자바스크립트 엔진과 비동기 작업을 처리하는 libuv 라는 라이브러리로 이뤄져있다. 참고로, libuv는 자바스크립트가 아니라 C++ 로 만들어진 라이브러리이다.


여기까지 싱글스레드(Single thread) vs 멀티스레드 (Multi thread) 편 끝!!
다음에는 이벤트 루프에 대해서 알아보자!!

자료 출처 및 참고 자료

profile
좋은 길로만 가는 "조은길"입니다😁

8개의 댓글

comment-user-thumbnail
2021년 6월 29일

싱글 스레드와 멀티 스레드 정리를 잘 해주셨네요. 다른 블로그 글들은 대충대충한 정리한 느낌이라 이해가 안 됐는데 덕분에 많이 배우고 갑니다.

1개의 답글
comment-user-thumbnail
2022년 8월 26일

깔끔하게 정리해주셔서 덕분에 크게 이해가 됐습니다. 감사합니다 :)

  • 혹시 싱글쓰레드의 장점으로 1번에 "문맥 교환은 여러 개의 프로세스가 하나의 프로세서를 공유할 때 발생하는 작업으로 많은 비용을 필요로 한다."
    이 부분은 "여러개의 쓰레드가 하나의 프로세스를 공유할 때 발생하는 작업" 이 아닌가요??
1개의 답글
comment-user-thumbnail
2022년 10월 20일

안녕하세요 질문이 있어서 댓글 답니다 !
"다시 말해서, 멀티 스레드 모델은 에러 발생 시 새로운 스레드를 생성하여 극복한다. "
이 부분에서 의문이 드는데요 !
스레드의 경우 같은 프로세스 내에 있는 스택을 제외한 메모리를 공유하기 때문에, 하나의 스레드에서 문제가 발생하면 전체 프로세스에 문제가 생긴다고 알고있습니다. 따라서, 위에 적으신 문장의 근거가 궁금합니다 !

1개의 답글
comment-user-thumbnail
2022년 11월 2일

귀한 글 감사합니다!

1개의 답글