JAVA - 쓰레드의 메모리 구성

이번엔 쓰레드의 메모리구성에 대해 알아보자.

쓰레드 생성 포스팅에서 쓰레드가 생성되면 가상머신은

쓰레드의 실행을 위한 별도의 메모리 공간을 할당한다고 했다.

그렇다면 이러한 별도의 메모리공간은

정확히 무엇을 의미하는걸까?

쓰레드의 가장 큰 역할은 별도의 실행흐름 형성이다. 그리고 별도의

실행흐름은 메소드의 호출을 통해서 형성된다.

즉 처음에 run메소드가 호출되고 run메소드 내에서 또다른 메소드를

호출하면서 main메소드와는 다른 흐름을 형성한다.

이렇듯 main 메소드와는 전혀 다른 실행흐름을 형성하기 위해서는

별도의 스택이 쓰레드에게 할당되어야 한다.

따라서 main 쓰레드 이외에 두 개의 쓰레드가 추가로 생성되면

가상 머신은 아래의 형태로 메모리를 구성한다.



위 그림에서 처럼 모든 쓰레드는 자신의 스택을 할당 받는다.

그러나 힙과 메소드 영역은 모든 쓰레드가 공유한다.

여기서 특히 힙이 공유됨에 주목하자. 힙 영역이 공유된다는 것은

모든 쓰레드가 동일한 힙 영역에 접근이 가능함을 의미하는 것이고

이는 다음과 같은 일이 가능함을 의미한다.


"A쓰레드가 만든 인스턴스의 참조값(주소값)만 알면

B쓰레드도 A쓰레드가 만든 인스턴스에 접근 가능"


그래서 쓰레드 사이에 데이터를 주고받아야 할 때에는

(쓰레드간의 통신이 필요할 때) 힙 영역을 활용한다

그럼 둘 이상의 쓰레드가 힙에 할당된 특정 메모리 영역에

함께 접근하는 예를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.jsp.ex;
 
class Sum{
    int num;
    public Sum() { num = 0; }
    public void addNum(int n) {num +=n;}
    public int getNum() { return num;}
}
 
class AdderThread extends Thread{
    Sum sumInst;
    int start, end;
    public AdderThread(Sum sum, int s, int e){
        sumInst = sum;
        start = s;
        end = e;
    }
    public void run(){
        for(int i = start; i<=end; i++)
            sumInst.addNum(i);
    }
}
class test2{
    public static void main(String[] args){
        Sum s=new Sum();
        AdderThread at1 = new AdderThread(s,1,50);
        AdderThread at2 = new AdderThread(s,51,100);
        
        at1.start();
        at2.start();
        
        try{
            at1.join();
            at2.join();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("1~100까지의 합 :" +s.getNum());
    }
}
cs



25line 에서 생성한 인스턴스의 참조값을

26,27line에서 생성하는 쓰레드 인스턴스에 생성자를

통해서 전달하고 있다. 따라서 두 개의 쓰레드는 25line에서

생성한 인스턴스에 접근이 가능하다.


29~30line에서는 start메소드 호출을 통해서 두 개의 쓰레드가 실행되었다.

이로써 두 쓰레드는 run메소드를 실행하면서 25line에서 생성한

인스턴스에 접근을 한다. 실제 접근은 20line에서 일어난다.



댓글

Designed by JB FACTORY