티스토리 뷰

+) 이펙티브 자바 스터디를하면서 volatile 변수에 대해 공부할일이 있어 짬짬히 적어보았다.

java 변수들은 물리적으로 어디에 저장될까?

레지스터

  • CPU 내부에 있는 빠른 메모리
  • 컴파일러는 최적화를 수행할때 자주 사용되는 변수를 레지스터에 보관
  • 스레드마다 CPU 레지스터는 독립적으로 동작, 스레드간의 직접 공유가 안된다. (동기화 문제의 원인)

메인 메모리

  • 대부분의 변수 여기에 저장
  • 모든 스레드가 공유하는 물리적 메모리 공간
  • CPU 캐시와 레지스터는 메인 메모리로부터 데이터를 가져오거나 씀

CPU 캐시

  • 계산할때 어딘가 값을 넣어야하니까.. 그 용도

자바 메모리 모델 JMM

  • 자바 메모리 모델에 따르면 한 스레드에서 변경한 값이 다른 스레드에게 보이려면 동기화를 하거나, volatile 메커니즘을 써야한다. -> 레지스터에 있는 값은 스레드간 직접 공유가 안되기 때문에
  • 동기화 이슈 = 레지스터와 메인 메모리 간의 동기화가 제대로 안되면 스레드 마다 서로 다른 값을 본다.

동기화 = 배타락? 배타적으로 막는다? 동기화할동안에는 접근하고 있는 스레드 말곤 아무도 못쓴다! 독점한다.
그래서 volatile을 쓰게되면 메모리이기때문에 스레드가 막 가져다 쓸 수 있는거임

그럼 volatile은 어떻게 가시성을 보장하느냐?

volatile = 휘발성, 메인 메모리에 직접 읽고 쓰는 것을 보장한다. 특정 스레드가 값을 수정하면 해당 값이 즉시 메모리에 반영되고 스레드간의 최신 값을 공유한다고 보는거다.

volatile이 원자성을 보장하지 않는다?

원자성이란 한번에 완전히 수행되고, 쪼개지지 않는 연산을 말한다.
스레드가 어떠한 로직을 수행하고 있을때 다른 스레드가 이를 방해하지 못하는 것도 원자성이 보장된다고 한다.

원자성은 세가지 특징이 있다.

  • 불가분성 = 연산이 시작되면 다른 연산이 끼어들 수 없는것
  • 중단 불가능성 = 중간에 중간되거나, 중간 상태가 노출되지 않는것
  • 일관성 보장 = 원자적 연산이 보장되면 여러 스레드가 동시에 연산을 수행해도 데이터가 일관적이어야 한다.

원자성은 기본원자성과 복합연산 원자성이라는게 있다.

volatile은 이때 기본 원자성만 보장한다. 단일 읽기&쓰기 수준에서의 원자성은 지원한다.
volatile int x; x = 5; 또는 int temp = x; 같은 단일 연산은 중간에 끼어들 틈 없이 수행된다.
하지만 i++ 같이 연산 자체가 한번의 메모리 접근이 아니라면 volatile 은 원자성을 보장해주지 않는다.

이럴때는 동기화(synchronization)나 원자적 클래스(예: AtomicInteger)는 복합 연산의 원자성을 보장해주면 된다.

내 개인적인 의견으로

volatile이 원자성을 보장해준다. -> 정확히는 틀린말이라고 본다. volatile은 가시성만을 보장해주고 특정 데이터타입(int,boolean등)에서의 단일 연산은 해당 데이터타입의 기본원자성이 보장되기때문애 volatile의 가시성과 합쳐져 동기화가 된다. 라고만 볼 수 있을 것같다.

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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
글 보관함