Java에서 volatile이 대체 뭡니까?

기르기르·2022년 9월 27일
1

어제 작성한 Singleton의 연장선은 아니지만 거기서 이어지는 이야기라고 할 수 있다. 가벼운 정리를 하려고 했던 그 녀석. Singleton이 생각보다 무거운 주제였고 해결 방안 중 하나였던 Double-checking Locking과 함께 쓰이는 모습을 보고 궁금증을 가지게 되었다. volatile이 뭘까?
이 녀석 또한.. 아직 한창 기초부터 배우는 단계인 내가 받아들이기에 무거운 주제였지만 어차피 남들과 같은 공부하는 것 똑같이 배우는 거 외에도 더 알아보자는 생각이 들어 공부할 겸 포스팅을 하기로 마음 먹었다.

Volatile 그 이전에..

자바에는 동시성 이슈 및 가시성 문제가 존재한다. 이 또한 내일 새로 포스팅하여 링크를 걸어두도록 하겠다. 이외에 알아야 할 중요한 것은 자바의 메모리 구조이다. 자바의 메모리 구조는 다음과 같다.

🔧Java의 메모리 구조

CPU 내에는 성능 향상을 위해서 L1 Cache가 내장되어 있는데 CPU 코어는 메모리에서 읽어온 값을 캐시에 저장하고, 캐시에서 값을 읽어서 작업한다. 값을 읽어올 때 우선 캐시에 해당 값이 있는지 확인하고 없는 경우에만 메인 메모리에서 읽어온다. 하지만 데이터가 쓰기 작업을 했다고해서 RAM으로 바로 쓰기 작업을 수행하지 않는다. 읽기 작업 또한 마찬가지다.
언제 RAM에서 데이터를 읽어 들여서 CPU Cache Memory를 업데이트할 지 보장하지 않는다.
아래 사진은 이 내용을 설명할 때 주로 사용하는 counter와 관련된 것이다.


volatile을 검색하면 가장 많이 나오는 이미지

오류가 생기는 read & write의 쉬운 예시로 counter를 설명한다. 이것은 조회수와 연관지을 수 있으며 더 나아가 자바를 처음 배울 때 간단히 만들어 보는 은행의 입출금 구현으로도 쉽게 오류를 발견할 수 있을 것이다.

Volatile 사용하게 만드는 오류

간단하게 말하자면..❗

스레드를 두 개 만들어 둔 상태에서 변수 a = 1로 선언하고, 스레드1은 a를 읽어와 ++하고 저장, 동시에 스레드 2는 저장된 a를 읽어오기를 1000번 반복 할 때 스레드 1에서 다 저장되기 전에 스레드2에서 값을 불러와 정확한 값이 나오지 않을 수 있다는 것이다.
이것은 자바의 가시성 문제라고 불리는 데이터 불일치이다.
이를 보완하기 위해 자바의 Volatile 키워드는 CPU의 chache가 아닌 RAM(Main memory)에서 값을 참조하도록 해준다.

Volatile이 뭘 하는건데?

Volatile은 어떤 것일까..❕❔

Volatile 키워드는 CPU메모리 영역에 캐싱된 값이 아니라 항상 최신의 값을 가지도록 CPU Cache Memory를 거치지 않고 RAM으로 직접 읽고 쓰는 작업을 수행하도록 한다. 쉽게 말하자면 정보를 CPU에 저장하고 다시 RAM에 저장하는게 아닌 RAM에 저장하고 RAM에서 불러오기때문에 항상 최신 값을 가질 수 있게 되는 것이다.
이것은 그리고 Volatile은 컴파일 단계에서 재배치-최적화를 하지 않도록 변경되어서 어제 포스팅한 Singleton의 극복 방안 - Double-Checked Locking에서 함께 사용되기도 했다. 그러나 좋은 활용성이 있을 것 같은 Volatile 키워드 역시 치명적인 결함이 존재한다.

📑Synchronized 키워드를 대체 할 수 있을까?

Volatile은 직접 동기화를 하는 것이 아닌 변수의 작업, 즉 read & write를 원자화 하는 것이기때문에 Synchronized대체 할 수 없다. 대신 Volatile 이 들어가는 변수를 Synchronized 키워드로 블럭을 묶어 동일한 효과를 기대할 수 있다.
둘의 사용 방식을 간단히 정리하면 Volatile은 특정 변수에 원자화 할 때 쓰이고 Synchronized는 여러 문장을 원자화 및 동기화할 때 사용한다.
그 외에도 Volatile은 이 스레드가 volatile 변수를 수정하기 전에 수정한 모든 변수들이 함께 메모리에 저장된다던가 Synchronized는 객체 단위로 Lock을 건다는 등의 차이점이 존재한다.

Volatile의 결함💦

첫째로는 비용적인 문제이다. 코드를 만들어 쓰는 것이 다 비지니스이기때문이 아닌 모든 것이 그렇겠지만 비용이 커지는 것은 이윤을 내야하는 회사의 입장에서 심각한 문제가 아닐까 생각한다. Volatile의 장점이지만 CPU가 아닌 RAM으로 사용하는 것은 회사에서 감당해야 할 COST가 커진다고 한다.

두번째로는 효과를 볼 수 있는게 한정된 상황이라는 것이다. 스레드 하나만 read & write를 하고 나머지 스레드는 read를 하는 상황에서야 효과적인 방법이다. 가시성 문제만 해결할 뿐 두 개 이상의 스레드가 write하는 상황에서는 여전히 동시성 문제를 해결할 수 없다. 이 분의 블로그 내용을 참조하면 상담가능시간, 자동인사여부 등 공통 환경변수. 즉 ,어떠한 스레드에서도 데이터가 일치하는 곳에서만 명시했다고 한다.

어렵다.. 어려워....😢

어제의 Singleton에 이어서 참 어려운 Volatile에 대해서 포스팅하기 위해 열심히 공부했건만.. Volatile도 웬만한 경우에 추천하지 않는 방식이였다. 물론 실무에 나가면 사용하는 경우를 보겠지만 컴퓨터 고장나면 구글링으로 겨우겨우 수리하고 컴퓨터가 어떤 식의 프로세스를 가지고있는지 몰랐던 내게 너무나 어려운 이야기임에 비해 허망한 결말로 느껴진다. 머릿 속에서 지우지는 않겠지만 언젠가라도 써먹을 일! 알려줄 일이 있으면 좋겠다. 허탈하다 뭐다 이런 얘기해도 사실 이번 주제의 공부를 괜히 했다라고는 생각하지 않는다. 다 쓸모가 있기때문에 많은 사람들이 공부하는 것이라고 생각하기 때문이다. 나에게도 도움이 다 되는 공부겠지! 그거 외에 아쉬운 점은 Volatile 관련해서 사람들이 많은 코드들을 예시로 들어놓았는데 그 코드를 한 눈에 이해할 수 없고 또 바로 내가 구현하지 못한 점이다.. 여기에 코드 좀 써넣고 싶었는데 학원에서 자바스크립트 강의 들으랴 Volatile 구글링하며 이해하랴 흑흑 하루가 너무 짧다. 그렇다고 이해 못 하고 글만 써재끼는건 아니지만!! 시간 내서 한 번 구현 해봐야겠다는 생각이 든다. 다른 사람 코드 따라 치는 것도 다 도움이 되니까ㅎ

0개의 댓글