[자바 무료 강의] 스레드와 메모리 - 코드라떼
Lesson List button
코스자바로 배우는 프로그래밍
hamburger button
강의스레드와 메모리최종수정일 2021-09-08
아이콘약 3분

노트 강의

우리는 앞서 “자바의 메모리 구조”라는 강의에서 Stack과 Heap, Method Area에 대해서 간략히 배웠습니다.
해당 강의에서는 Thread를 모른 채 하나의 실행 흐름만 생각하며 배웠었습니다. 이제 Thread와 메모리 구조에 대해서 좀 더 연결해서 배워보는 시간입니다.

이번에는 쉬어가는 강의입니다.


Thread와 메모리


Thread와 메모리 관계를 들어가기 전에 기억이 안날 수도 있으므로 이전에 배웠던 Stack과 Heap, Method Area에 대해 다시 한번 정리하고 시작하겠습니다.


자바의 메모리 구조

java memory


Stack

Stack은 Stack Frame 단위로 나누어져 있으며, Thread가 새로운 메서드가 실행되거나 탈출할 때마다 Stack Frame이 생성 및 소멸을 합니다. Stack Frame에는 메서드 내부의 로컬 변수를 관리하는 Local Variables Array와 연산 과정을 일시적으로 저장하는 Operand Stack, 그리고 메서드 종료 시 돌아와야 할 주소나 그 외 메서드에 대한 정보를 가지고 있는 Frame Data로 나뉘어 있습니다.


Heap

Heap은 인스턴스 생성 시 인스턴스가 저장되는 메모리 공간입니다. 인스턴스는 참조 여부에 따라 Garbage Collector에 의해 수집 및 소멸되며, 참조 값을 이용하여 인스턴스의 메모리 공간에 접근할 수 있습니다. 문자열 상수를 관리하는 String Constant Pool이 Heap 메모리 공간에 포함되어 있습니다.


Method Area

Method Area는 클래스 정보, 필드 정보, 메서드에 대한 정보, 인터페이스, 심볼릭 레퍼런스 등 자바 프로그램을 실행시키기 위한 다양한 정보를 가지고 있습니다. 클래스 정적 변수와 클래스 정적 메서드도 Method Area 메모리 공간에 포함되며 상수 관련한 데이터를 가지고 있는 Run-Time Constant Pool도 포함되어 있습니다.


Thread에서 자바 메모리를 어떻게 이용하는가

thread memory

Thread는 Stack을 제외한 Heap 메모리와 Method Area 메모리 공간을 공유합니다.

각 Thread는 자기 자신의 Stack Memory를 가지고 있으며, Thread 끼리 Stack memory 공간을 침범할 수 없습니다.

이 같은 특성을 다시 말하자면 인스턴스 변수나 정적 변수는 Thread가 공유할 수 있으나, 메서드 내의 로컬 변수(지역 변수)는 Thread Stack에서 운용되므로 다른 Thread와 공유할 수 없습니다.



예제 코드

public class Cafe implements Runnable { public String cafeName = "카페"; // Thread가 호출하는 makeCoffee는 // 다른 스레드가 침범할 수 없다 // 다만 메서드 내에서 로컬 변수만이 아닌 // 인스턴스 변수를 사용한다면 다른 얘기이다 public int makeCoffee() { int salt = 3; int sugar = 2; int caffeine = 20; return salt + sugar + caffeine; } public void run() { // 각 스레드가 로컬 변수에는 접근할 수 없다 System.out.println(makeCoffee()); // 각 스레드는 인스턴스 변수에 접근할 수 있다 System.out.println(cafeName); } }
copy
public class Main { public static void main(String[] args) { Cafe cafe = new Cafe(); // Main Thread에서 변수값 변경 cafe.cafeName = "카페A"; Thread threadA = new Thread(cafe); Thread threadB = new Thread(cafe); threadA.start(); threadB.start(); // 25 // 카페A // 25 // 카페A // Main Thread에서 변경한 값이 서브 스레드에서 // 접근할 때도 변경된 값으로 출력된다 } }
copy

image

로컬 변수(지역 변수) 라 함은 makeCoffee() 메서드 내부에 선언된 변수처럼 Stack에 일시적으로 할당 했다가 사용하고 소멸되는 변수를 말합니다.

그러나 인스턴스 변수는 Cafe 인스턴스가 소멸되지 않는 한 어느 Thread에서도 접근이 가능하므로, 값이 변경될 경우 변경된 값을 읽을 수 있습니다.

이유는 Heap 메모리를 공유하므로 참조값을 통해 Heap 메모리의 인스턴스에 접근할 수 있기 때문입니다.

인스턴스 변수 뿐만 아니라 정적 변수도 공유합니다.

그러므로, 인스턴스 변수나 정적 변수는 Thread 간에 영향을 줄 수 있으므로 특별한 이유가 아닌 이상 변경되지 않는 값을 읽는 것은 상관 없어도, 변경될 수 있는 값을 읽는 것은 피하는 것이 좋습니다.

도전자 질문
작성된 질문이 없습니다
이용약관|개인정보취급방침
알유티씨클래스|대표, 개인정보보호책임자 : 이병록
이메일 : cs@codelatte.io
사업자등록번호 : 824-06-01921
통신판매업신고 : 2021-성남분당C-0740
주소 : 경기도 성남시 분당구 대왕판교로645번길 12, 9층 24호
Lesson List button
코스자바로 배우는 프로그래밍
hamburger button
강의스레드와 메모리최종수정일 2021-09-08
아이콘약 3분

노트 강의

우리는 앞서 “자바의 메모리 구조”라는 강의에서 Stack과 Heap, Method Area에 대해서 간략히 배웠습니다.
해당 강의에서는 Thread를 모른 채 하나의 실행 흐름만 생각하며 배웠었습니다. 이제 Thread와 메모리 구조에 대해서 좀 더 연결해서 배워보는 시간입니다.

이번에는 쉬어가는 강의입니다.


Thread와 메모리


Thread와 메모리 관계를 들어가기 전에 기억이 안날 수도 있으므로 이전에 배웠던 Stack과 Heap, Method Area에 대해 다시 한번 정리하고 시작하겠습니다.


자바의 메모리 구조

java memory


Stack

Stack은 Stack Frame 단위로 나누어져 있으며, Thread가 새로운 메서드가 실행되거나 탈출할 때마다 Stack Frame이 생성 및 소멸을 합니다. Stack Frame에는 메서드 내부의 로컬 변수를 관리하는 Local Variables Array와 연산 과정을 일시적으로 저장하는 Operand Stack, 그리고 메서드 종료 시 돌아와야 할 주소나 그 외 메서드에 대한 정보를 가지고 있는 Frame Data로 나뉘어 있습니다.


Heap

Heap은 인스턴스 생성 시 인스턴스가 저장되는 메모리 공간입니다. 인스턴스는 참조 여부에 따라 Garbage Collector에 의해 수집 및 소멸되며, 참조 값을 이용하여 인스턴스의 메모리 공간에 접근할 수 있습니다. 문자열 상수를 관리하는 String Constant Pool이 Heap 메모리 공간에 포함되어 있습니다.


Method Area

Method Area는 클래스 정보, 필드 정보, 메서드에 대한 정보, 인터페이스, 심볼릭 레퍼런스 등 자바 프로그램을 실행시키기 위한 다양한 정보를 가지고 있습니다. 클래스 정적 변수와 클래스 정적 메서드도 Method Area 메모리 공간에 포함되며 상수 관련한 데이터를 가지고 있는 Run-Time Constant Pool도 포함되어 있습니다.


Thread에서 자바 메모리를 어떻게 이용하는가

thread memory

Thread는 Stack을 제외한 Heap 메모리와 Method Area 메모리 공간을 공유합니다.

각 Thread는 자기 자신의 Stack Memory를 가지고 있으며, Thread 끼리 Stack memory 공간을 침범할 수 없습니다.

이 같은 특성을 다시 말하자면 인스턴스 변수나 정적 변수는 Thread가 공유할 수 있으나, 메서드 내의 로컬 변수(지역 변수)는 Thread Stack에서 운용되므로 다른 Thread와 공유할 수 없습니다.



예제 코드

public class Cafe implements Runnable { public String cafeName = "카페"; // Thread가 호출하는 makeCoffee는 // 다른 스레드가 침범할 수 없다 // 다만 메서드 내에서 로컬 변수만이 아닌 // 인스턴스 변수를 사용한다면 다른 얘기이다 public int makeCoffee() { int salt = 3; int sugar = 2; int caffeine = 20; return salt + sugar + caffeine; } public void run() { // 각 스레드가 로컬 변수에는 접근할 수 없다 System.out.println(makeCoffee()); // 각 스레드는 인스턴스 변수에 접근할 수 있다 System.out.println(cafeName); } }
copy
public class Main { public static void main(String[] args) { Cafe cafe = new Cafe(); // Main Thread에서 변수값 변경 cafe.cafeName = "카페A"; Thread threadA = new Thread(cafe); Thread threadB = new Thread(cafe); threadA.start(); threadB.start(); // 25 // 카페A // 25 // 카페A // Main Thread에서 변경한 값이 서브 스레드에서 // 접근할 때도 변경된 값으로 출력된다 } }
copy

image

로컬 변수(지역 변수) 라 함은 makeCoffee() 메서드 내부에 선언된 변수처럼 Stack에 일시적으로 할당 했다가 사용하고 소멸되는 변수를 말합니다.

그러나 인스턴스 변수는 Cafe 인스턴스가 소멸되지 않는 한 어느 Thread에서도 접근이 가능하므로, 값이 변경될 경우 변경된 값을 읽을 수 있습니다.

이유는 Heap 메모리를 공유하므로 참조값을 통해 Heap 메모리의 인스턴스에 접근할 수 있기 때문입니다.

인스턴스 변수 뿐만 아니라 정적 변수도 공유합니다.

그러므로, 인스턴스 변수나 정적 변수는 Thread 간에 영향을 줄 수 있으므로 특별한 이유가 아닌 이상 변경되지 않는 값을 읽는 것은 상관 없어도, 변경될 수 있는 값을 읽는 것은 피하는 것이 좋습니다.

도전자 질문
작성된 질문이 없습니다
이용약관|개인정보취급방침
알유티씨클래스|대표, 개인정보보호책임자 : 이병록
이메일 : cs@codelatte.io|운영시간 09:00 - 18:00(평일)
사업자등록번호 : 824-06-01921|통신판매업신고 : 2021-성남분당C-0740
주소 : 경기도 성남시 분당구 대왕판교로645번길 12, 9층 24호(경기창조혁신센터)