[ 컴퓨팅 환경 ]
현대에서 우리가 사용하는 모든 컴퓨터들은 멀티 프로세서, 코어, 스레드 환경이다. 자바는 JVM을 통해 운영체제를 통해 CPU의 쓰레드에 task를 할당한다.
[ 메모리 모델과 메모리 구조 ]
다른 사람들이 포스팅해놓은 블로그를 보면, 제목이 메모리 모델이라고 적혀있는데 메모리 구조를 설명하는 경우가 많다. 자바에는 volatile를 사용하여 cpu l1캐시에 캐싱될 변수를 메인 메모리에 할당하여 동시성 문제를 해결하고, final 변수 상를 정의하며, syncchronized를 사용하여 동일한 자원에 대한 동시 접근을 막는다.
위에서 언급한 3개 혹은 그 이상의 키워드들이 어떠한 순서대로 할당되고 실행되는지를 정의하는게 메모리 모델이고, 메모리 구조는 JVM이 어떻게 생겨먹었는지 설명하는 것이 메모리 구조이다.
그렇다면 사람들이 메모리 모델을 잘 못 이해하고 있는 이유는 무엇일까?
메모리 모델은 솔직히 알고 있어야하는 이유가 딱히 없다. 변태적인 성향을 가지고 자바에서 사용되는 키워드들이 어떻게 동작하는지 자세히 알고 싶은 사람만 JLS DOCS를 읽어보며 알아가야하는 내용이다.
일반 사람들은 '그냥' 스펙으로 명시된 JAVA 언어를 사용하는 것이다. JVM도 개발한 회사마다 다 다르지만, 우리는 거의 똑같은 문법의 언어를 사용하면 JVM이 알아서 해결해준다. 우리가 JVM의 구현체까지 알아야할 필요가 없다는 뜻이다.
[ 메모리 모델 ]
메모리 모델이라고해서 어려운 것이 아니다.
import java.util.*;
import java.lang.*;
import java.io.*;
// The main method must be in a class named "Main".
class Main {
public static void main(String[] args) {
Car car = new Car("mycar", "500");
car.info();
}
}
class Car {
private String ps;
private String name;
public Car(String name, String ps){
this.name = name;
this.ps = ps;
}
public void info() {
System.out.println("name : "+ this.name + " | ps : " + this.ps);
}
}
다음과 같은 코드가 있다고 생각하자.
그럼 Car이 만들어지는 과정은 어떻게 될까?
1. 메모리 할당 받음 Object a = new Car('a','1');
2. 속성 할당 // a.name = 'a';, a.ps = '1'
3. 변수 할당 // Car car = (Car) a;
이런 매커니즘을 정의하는 것이 메모리 모델이다. 만약 메모리 모델이 위와 다르다면 다음과 같이도 할 수 있을 것 같다
1. 메모리 할당 받음 Object a = new Car('a','1');
2. 변수 할당 // Car car = (Car) a;
3. 속성 할당 // a.name = 'a', a.ps = '1'
하지만 2번째 정의한 방법대로 구현이 되었다고 한다고 가정하면, 멀티 스레드 환경에서는 불안정한 초기화 방식이다. 객체에 값이 할당되기도 전에 해당 객체를 가져다 사용할 수 있기 때문이다.
여기서 final이라는 키워드가 있다면, 객체가 초기화되어야만 사용할 수 있게 스펙으로 정의되어 있기 때문에 1번 방식대로 흘러갈 것이다.
메모리 모델을 공부하려면 내용이 엄청 많은데, 이번에는 final만 보고 넘어가겠다.