스레드(thread)란?
'실행의 단위, 프로세스를 구성하는 실행 흐름의 단위를 뜻한다.'
실행의 흐름 단위가 1개라면 단을 프로세스, 실행 흐름의 단위가 여러개라면 멀티 스레드 프로세스이다.
실행에 필요한 최소한의 정보만(프로그램 카운터, 레지스터, 스택)을 유지한체 프로세스의 자원을 공유하여 실행한다.
스레드가 왜 필요할까?
윈도우 OS 기준 멀티 프로세스 기반 OS이다.
즉 여러개의 프로세스를 실행할 수 있는데 여러개의 프로세스를 실행할 때 '컨텍스트 스위칭'이 발생한다.
컨텍스트 스위칭(CS라 하겠다)을 간단하게 말하면 프로세스의 상태 정보를 저장하고 복원하는 일련의 과정을 뜻한다.
이 CS는 아무리 못해도 1초에 수십번 발생하기 때문에 성능저하의 원인이 된다.(멀티 프로세스 기반 OS의 최대 단점중 한가지 이다)
이러한 성능저하의 원인을 조금 완화 시키기 위해서는 저장하고 복원하는 컨텍스트 정보의 개수를 줄여주면 된다.
즉, 프로세스의 상태 정보를 줄여야 한다는 결론이 나온다.
CS가 발생하는 가장 근본적인 이유는 프로세스들은 서로 완전히 독립적인 메모리 구조를 가지고 있기 때문이다.
A프로세스를 실행하고 있다가 B프로세스를 실행할 때 CPU뿐만 아니라 메모리 까지 B로 다 채워야 한다.이때 CS가 발생하고 시간이 오래 걸린다.
근데 A, B 프로세스가 완전히 별개의 프로세스가 아니라 50%정도 공유하는 구조라면 CS 발생시 저장하고 복원하는 정보가 반으로 줄어들지 않을까? 하는 생각을 기반으로 탄생한 것이 스레드이다.
스레드의 메모리 구조와 스택
스레드를 생성할 때마다, 각 스레드를 위한 스택을 생성할 뿐 code, data, heap영역은 공유하게 된다.
스택은 왜 각 스레드마다 생성할까?
스택이란?
'함수 호출시 전달되는 인자, 되돌아갈 주소값 및 함수 내에서 선언하는 변수등을 저장하기 위한 메모리 공간이다.'
공간이 독립적이라 추가적인 실행 흐름을 만들 수 있다는 의미가 된다.
즉, 실행 흐름의 추가를 위한 최소 조건이 독립된 스택의 제공이다.
스레드마다 독립적인 실행 흐름을 만들어주기 위해 스레드 별로 스택을 만들어주는 것이다.
Windows에서의 프로세스와 스레드
윈도우 OS한정으로 프로세스는 단순히 스레드를 담는 상자에 지나지 않는다.
따라서 실제로 프로그램의 흐름을 형성하는 것은 스레드가 된다.
위에서 알아본 개념을 통해 스레드를 사용하면 CS가 빨라진다. 왜냐하면 공유하는 영역이 많아졌기 때문이다.(저장하고 복원하는 데이터가 줄어들었기 때문)
근데 단순히 공유하는 영역이 많아졌기 때문에 CS가 빠르다 하기 보다 왜 CS가 빨라졌는지 조금더 알아보자.
우선 레지스터 측면에서 보면 pc(프로그램 카운터)는 실행해야하는 명령어가 있는 위치를 가르키다 보니, 이 레지스터는 컨텍스트 스위칭을 하더라도 영향을 받지 않을거같지만 그렇지 않다.
코드영역을 공유하기는 하지만 스레드 별로 Main함수를 독립적으로 가지고 있고, 함수 호출도 독립적으로 진행되기 때문에 스레드별로 pc가 가져야할 값이 다르기 마련이다.
음? 그럼 왜 빠르냐? 할 수 있지만 '캐쉬 메모리'영역 관점에서 다시 보도록 하자.
캐쉬란?
CPU에서 한 번 이상 읽어들인 메인 메모리의 데이터를 저장하고 있다가 CPU가 다시 그 메모리에 저장된 데이터를 요구할 때, 메인 메모리를 통하지 않고 바로 값을 전달해주는 용도의 메모리이다.
그렇기 때문에 CPU와 메인 메모리 사이에 위치한다.
이런 상황에 프로세스 컨텍스트 스위칭이 발생했다고 하자.
그럼 캐쉬가 지금껏 열심히 저장해놓은 데이터들이 한 순간에 무너지고 새로운 기준으로 하여금 다시 캐쉬 정보를 쌓아 올려야한다. 왜냐하면 프로세스 사이에서는 공유하는 메모리가 하나도 없기 때문에 다시 한번 CPU가 0x3000번지의 데이터를 요구한다 할지라도 새로운 프로세스의 0x3000번지의 데이터를 전달 해주어야 하기 때문이다.
어쩔 수 없이 캐쉬는 기존에 저장해놓은 데이터를 완전히 버리고 새로 쌓아 나가야 한다.
이것이 프로세스 컨텍스트 스위칭에 부담이 되는 요소중 하나이다.
반면, 스레드라면 캐쉬를 비울 필요가 없다.
A 스레드가 요구하는 0x1300번지의 데이터는 B 스레드가 요구하는 0x1300번지 데이터와 동일하다.
즉, A 스레드 실행 시 저장된 캐쉬 데이터는 B 스레드 입장에서도 같은 의미를 지닌다는 것이다.
윈도우에서는 스케쥴러가 스레드를 스케줄링을 하는데 이때 컨텍스트 스위칭이 발생한다.
그러나 같은 프로세스내의 스레드간 컨텍스트 스위칭은 프로세스간 컨텍스트 스위칭 보다 훨씬 빠르다.
반면, A 프로세스 <-> B 프로세스간의 컨텍스트 스위칭은 일반적은 프로세스 컨텍스트 스위칭과 별반 다를게 없다.
정리
프로세스를 많이 생성하면 잦은 컨텍스트 스위칭으로 인해 성능 저하가 발생한다. 따러서 컨텍스트 스위칭을 하되 이를 완화하기 위해 컨텍스트 양 자체를 줄이는 방법으로 스레드가 탄생했다.
스레드는 각각의 독립적인 실행 흐름을 저장하기 위한 스택을 제외하고 코드, 힙, 데이터를 공유하게 함으로써 컨텍스트 양을 줄여 컨텍스트 스위칭 비용을 줄였다.
'CS' 카테고리의 다른 글
Stack Frame과 함수 호출 규약(__stdcall) (1) | 2024.04.28 |
---|---|
[CS] 가상 메모리와 페이징 (0) | 2023.08.15 |
[CS] 스와핑(Swapping) (0) | 2023.08.09 |
[CS] 논리주소와 물리주소 (0) | 2023.08.07 |
[CS] Context Switching(문맥 교환) (0) | 2023.08.05 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!