본문 바로가기
개념공부/BackEnd

스레드와 메모리구조

by 29살아저씨 2022. 6. 21.
반응형

프로세스 vs 스레드 (Thread)

프로세스란?

- 프로그램을 실행시켰을 때 메모리상에 올라가 동작되고있는 과정

 

스레드란?

- 프로세스 내에서 실행되는 흐름의 단위

1. main() 안의 실행문들이 하나의 Thread이다.

2. main() 이외의 또 다른 스레드를 만들려면 Thread 클래스를 상속하거나, Runnable 인터페이스를 구현한다.

3. 멀티스레드로 작업을 할 때에는 각 스레드끼리 정보를 주고받을 수 있어 처리 과정의 오류를 줄일 수 있다.

4. Java 메모리구조 에서는 스레드가 생성될 때 마다 각각 독립적인 Stack영역, PC영역, NMS(Native Method Stack)영역을 가지게 된다.

 

메모리 구조

- 선택 이유

  • 코드를 작성하고 프로그램을 개발 해봤지만, 컴퓨터 내부에서는 어떻게 실행되는지 궁금했음
  • 스레드를 학습하면서 메모리 구조에 대해 학습이 필요했음

프로젝트도 해보고, 수업을 들으면서 프로그램도 짜보았지만, 정작 코드 내에서 돌아가는 방식만 생각하고, 코드 흐름만 이해하는 식으로 개발을 진행했었다. 정작 코드가 컴퓨터 내부에서 실행되는 과정에 대해서는 자세하게 알지 못한채,,

코드가 컴퓨터 내부에서 돌아가는 과정에 대해서 알고 개발을 진행한다면 개발의 전체적인 측면에서 이해도를 높일 수 있을거라 생각하여 이 주제를 선택하게 되었다. 또한 스레드를 학습하면서 스레드가 어떻게 동작하는지 궁금했기 때문에 이 주제를 선정하게 되었다.

 

- 메모리란?

메모리란 [RAM(Random Access Memory)] 단기 데이터 저장소로, 정보에 빠르게 액세스 할 수 있도록 컴퓨터가 실시간으로 사용하는 정보를 저장하는 공간. 많은 프로그램을 실행시키려면 더 많은 메모리가 필요하다!

 

- 그렇다면 내가 코딩한 프로그램은 메모리에 어떻게 올라갈까?

Java를 예로 들어보자, 우리가 작성하는 코드들은 Java 컴파일러를 통해 .class 파일로 만들어 지고(소스코드를 바이트코드로 변환), 이후 이를 JVM이 읽고 실행하게된다.

이런 전반적인 과정을 거쳐 코드가 프로그램이 되고, 코드가 실행이 되면서 작성한 로직에 맞게 각각의 메모리 위치에 올라가 프로그램을 실행 하게 된다. 프로그램이 실행되고 있는 것, 이를 프로세스라고 한다!

 

- 각각의 메모리 위치?

메모리도 위 사진과 같이 크게는 4가지로 분류할 수 있다. 

낮은주소인 Text영역 부터 Data영역, Heap영역, 높은주소의 Stack영역까지 나누어 볼 수 있다.

여기서 나온 6가지 단어들에 대해 좀 더 자세히 알아보자

 

1,2. 낮은주소, 높은주소란?

메모리주소는 메모리 위치에 대한 식별자로, 메모리에 저장된 데이터를 쉽게 가져올 수 있도록 하는 것이다.(ex. 포인터, 배열 주소값) 여기서 낮은주소는 말 그대로 0x00000000부터 들어가는 주소 값이고, 높은주소는 0xFFFFFFFF로 들어가는 주소 값으로 이해하면 된다. 

중요한 것은 낮은주소, 높은주소의 개념이 아니라 각 영역에 대한 설명이니 아래 부분을 한번 알아보도록 하자.

 

 

 

2. Text 영역

 

텍스트 영역은 쉽게 말하면 코드를 실행하기 위해 저장되어있는 영역이다.

흔히 코드 영역이라고도 하는데, 프로그램을 실행시키기 위해 구성되는 것들이 저장되는 영역이다. 제어문, 함수, 상수들이 이 영역에 저장이 된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. Data 영역

 

데이터 영역은 작성한 코드에서 전역변수, 정적변수 등이 저장되는 공간이다.

이들의 특징을 보면 메인함수 전에 선언되어 프로그램이 끝날 때 까지 메모리에 남아있는 변수들. 이라는 특징이 있다.

 

좀 더 구체적으로 보자면 초기화된 변수영역과, 초기화 되지않은 변수영역으로 나뉠 수 있는데 지금은 간단하게 데이터 영역으로 이해를 하고 넘어가자.

 

 

 

 

 

 

4. Heap 영역

 

힙 영역은 '사용자에 의해 관리되는 영역'이다.

흔히 동적으로 할당 할 변수들이 여기에 저장된다고 보면 된다.

 

Java나 C++에서 new 연산자로 생성하는 경우 또는 class, 참조 변수들도 힙 영역에 차지하게 된다. 

 

Heap 영역은 낮은주소에서 높은주소 로 메모리에 할당된다.

 

 

 

 

Heap 영역에 저장되는 참조 타입들

 

 

 

 

5. Stack 영역

 

스택 영역은 함수를 호출 할 때 지역변수, 매개변수들이 저장되는 공간이다.

(main 함수안의 변수들도 마찬가지!)

 

함수가 종료되면 해당 함수에 할당된 변수들을 메모리에서 해제시킨다. (Stack 자료구조의 pop같은 기능) 

 

Stack 영역은 Heap 영역과 반대로 높은주소에서 낮은주소로 메모리에 할당된다.

 

 

 

 

※ 왜 힙 영역과 스택 영역은 다른 방향을 가질까?

1. 스택이 항상 커널의 반대 방향으로 자라기 때문에 영원히 커널을 만나지 않게 됩니다. 다시말해, 스택이 아무리 커져도 접근 불가 영역인 커널을 건드리지 않게 됩니다.

2. 힙과 관련이 있습니다. 힙 영역은 스택과는 달리 새로운 데이터가 추가될 수록 더 큰 메모리 주소를 할당받게 됩니다. 이처럼 스택 영역과 힙 영역이 공유 라이브러리 영역을 가운데에 두고 서로 마주보는 형태를 갖기 때문에 메모리 공간을 알뜰 하게 활용 할 수 있게 됩니다

 

 

6. 전체 구조

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Memory Overflow

- Heap 영역

Java 같은 경우는 Gc(Garbage Collector)가 있어서 참조되지 않는 데이터들의 경우 알아서 메모리를 반납해줘서 Heap 메모리 관리에 수월. 하지만 C나 C++은 더이상 쓰지 않는 동적 할당 변수들을 해제해줘야한다. 만약 해제하지 않으면 흔히 말하는 메모리 누수(Memory Leak)가 발생한다. 또한 계속 쌓이다보면 할당된 Heap메모리 용량을 벗어나 에러가 발생하게 된다.

- Stack 영역

Stack Overflow는 흔히 '재귀함수' 호출 시 발생한다.

기저조건이 갖춰져 있지 않은 함수의 경우 무한히 호출되면서 Stack영역에 해당 함수의 지역변수, 매개변수 등의 데이터가 계속해서 쌓이게 되므로, Stack영역의 범위를 벗어나 Overflow가 발생하게 된다.

 

자바의 메모리구조

  • Java 프로그램이 실행되면 JVM은 운영체제로 부터 필요한 메모리를 할당받음
  • 메모리 구조에 맞게 프로그램이 실행

 

- JVM의 Memory Area 구조

 

1) Method Area

  • JVM이 실행되면서 생기는 공간이다.
  • Class 정보, 전역변수 정보, Static 변수 정보가 저장되는 공간이다.
  • Runtime Constant Pool 에는 말 그대로 '상수' 정보가 저장되는 공간이다.
  • 모든 스레드에서 정보가 공유된다.

2) Heap

  • new 연산자로 생성된 객체, Array와 같은 동적으로 생성된 데이터가 저장되는 공간
  • Heap에 저장된 데이터는 Garbage Collector 가 처리하지 않는한 소멸되지 않는다.
  • Reference Type 의 데이터가 저장되는 공간
  • 모든 스레드에서 정보가 공유된다.

3) Stack

  • 지역변수, 메소드의 매개변수와 같이 잠시 사용되고 필요가 없어지는 데이터가 저장되는 공간
  • Last In First Out, 나중에 들어온 데이터가 먼저 나간다
  • 만약, 지역변수 이지만 Reference Type일 경우에는 Heap 에 저장된 데이터의 주소값을 Stack 에 저장해서 사용하게 된다.
  • 스레드마다 하나씩 존재한다.

4) PC Register

  • 스레드가 생성되면서 생기는 공간
  • 스레드가 어느 명령어를 처리하고 있는지 그 주소를 등록한다.
  • JVM이 실행하고 있는 현재 위치를 저장하는 역할
  • 스레드마다 하나씩 존재한다.

5) Native Method Stack

  • Java 가 아닌 다른 언어 (C, C++) 로 구성된 메소드를 실행이 필요할 때 사용되는 공간
  • 스레드마다 하나씩 존재한다.

 

! 그럼 이제 스레드에 대해 자세히 알아보자 !

위에서 설명했다시피 스레드는 프로세스 내에서 Heap, Method Area영역을 공유하고, 독립적인 Stack, Register, NMS영역을 가진다. 이쯤되서 다시 스레드에 대한 개념을 잡아보면,

  • 한 프로세스 내에서 동작되는 여러 실행 흐름으로 프로세스 내의 주소 공간이나 자원을 공유할 수 있다.
  • 이 경우 각각의 스레드는 독립적인 작업을 수행해야 하기 때문에 각자의 스택 PC 레지스터 값을 갖고 있다.

그럼 왜 스레드는 각자의 스택과 PC 레지스터 값을 가지고 있을까?

 

한 순간에 하나의 스레드만 실행이 가능하다.

- 스택을 스레드마다 독립적으로 할당하는 이유

  • 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소값 및 함수 내에서 선언하는 변수 등을 저장하기 위해 사용되는 메모리 공간이므로 스택 메모리 공간 독립적이라는 것은 독립적인 함수 호출이 가능하다는 것이고, 이는 독립적인 실행 흐름이 가능하게 한다.
  • 따라서 독립적인 실행 흐름을 위한 최소 조건으로 독립된 스택을 할당한다.

 

- PC Register를 스레드마다 독립적으로 할당하는 이유

  • PC 값은 스레드가 명령어의 어디까지 수행하였는지를 나타나게 된다.
  • 스레드는 CPU를 할당받았다가 스케줄러에 의해 다시 선점당한다. 그렇기 때문에 명령어가 연속적으로 수행되지 못하고, 어느 부분까지 수행했는지 기억할 필요가 있다.
  • 따라서 PC 레지스터를 독립적으로 할당한다.

 

  1. main()함수[1번 스레드] 가 서버 프로그램에 접속하려는 클라이언트를 대기한다.
  2. Socket(ip,9000)에 접속하면 Main Thread(2번 스레드)가 활성화 되면서 클라이언트가 Socket(ip,9000)으로 보내는   방 생성 신호를 대기한다.
  3. 클라이언트가 Socket(ip,9000)으로 방 생성 신호를 보내면 포트번호 9001(+1씩)를 가진 Socket이 생성되고 생성된 채팅방 스레드[3번 스레드]가 생성된다.
    1. 채팅방 스레드[3번 스레드]는 Socket(ip,9001~)로 접속하려는 클라이언트들을 대기한다.
  4. 클라이언트가 방 입장을 클릭하여 Socket(ip,9001~) 에 접속을 하면 Chat Thread()[4번 스레드]가 활성화되고, 이 스레드는 채팅입력, 방 인원들에게 보내주는 역할을 한다.

 

 

아래는 인터넷 검색하면서 발견한 짤

 

 

Reference

- 자바 메모리 관리 : 스택 & 힙

https://yaboong.github.io/java/2018/05/26/java-memory-management/

 

자바 메모리 관리 - 스택 & 힙

개요 Java 에서 메모리 관리는 어떻게 이루어지는지 알아보기 위함. Stack 과 Heap 영역 각 역할에 대해 알아본다. 간단한 코드예제와 함께 실제 코드에서 어떻게 Stack 과 Heap 영역이 사용되는지 살펴

yaboong.github.io

- 자바스크립트는 왜 싱글 스레드일까?

https://chanyeong.com/blog/post/44

 

자바스크립트는 왜 싱글 쓰레드일까? :: chanyeong

자바스크립트라는 언어는 싱글 쓰레드 언어라고 알려져있다. 보통 싱글 쓰레드라고 하면 한 번에 하나의 작업만 수행할 수 있다고 생각한다. 그렇다면 자바스크립트를 주로 사용하는 웹 사이트

chanyeong.com

- 메모리구조 ★★★(추천)

https://st-lab.tistory.com/198

 

메모리 구조 [Memory Structure]

안녕하세요. 오늘은 제목에서 밝혔듯 메모리 구조에 대해 알아보려 합니다. 흔히 메모리라고 하면 RAM을 지칭하는데요, 보통 컴퓨터 구조에 대해 학습하시거나 배우셨던 분들은 알겠지만 메모리

st-lab.tistory.com

- Java 메모리구조

https://www.youtube.com/watch?v=AWXPnMDZ9I0 

- 런타임과 컴파일타임

https://spaghetti-code.tistory.com/35

 

런타임이란? 컴파일타임 과의 차이는?

런타임(Runtime)과 컴파일타임(Compiletime)의 차이점은 무엇인가? 런타임과 컴파일타임에 대해 가장 쉽게 설명한 글이 있어 번역해 보았습니다. 원문보기 런타임(Runtime)과 컴파일타임(Compiletime)은 소

spaghetti-code.tistory.com

- 스레드란 무엇인가?

https://goodgid.github.io/What-is-Thread/

 

쓰레드(Thread)란 무엇인가?

Index

goodgid.github.io

 

반응형

댓글