Java

[Java] 공유객체와 volatile 키워드

Razelo 2021. 1. 5. 19:20

공유객체란 무엇일까?

공유객체는 하나의 객체를 여러 개의 Thread가 사용한다는 의미이다. 

 

volatile은 무엇일까?

volatile은 해당 키워드로 선언된 변수를 컴파일러의 최적화 대상에서 제외시킨다는 의미이다. 

 

그래서 값이 변경되는 즉시 변수에 적용시킨다. 그런데 하나의 Thread가 아닌 여러 Thread가 Write하는 상황에서는 적합하지 않다고 한다. 

 

Java에서 volatile은 Java 변수를 Main Memory에 저장하겠다는 것을 명시하는 키워드이다. 

그래서 변수의 값을 읽을때 CPU 캐시에 저장된 값이 아니라 Main Memory에서 읽게 되는 것이다. 

그리고 마찬가지로 변수의 값을 쓸때도 Main Memory에까지 작성하는 것이다. 

 

왜 volatile 키워드가 필요할까? 

 

volatile 변수를 사용하고 있지 않은 MultiThread 어플리케이션에서는 Task를 수행하는 동안에 성능 향상을 위해서 Main Memory에서 읽은 변수 값을 CPU Cache에 저장한다고 한다. 

 

그런데 CPU Cache에 저장하다보니 만약 Multi Thread 환경이라면 Thread가 변수 값을 읽어올 때 각각의 CPU Cache에 저장된 값이 다르기 떄문에 변수 값 불일치 문제가 발생한다고 한다. 

 

예를 들어서 설명해보자. 

 

Thread 1, 2가 있다고 가정할때 Thread 1은 계속해서 counter 변수 값을 증가시키는 동작을 하지만 Thread 2는 읽어오는 연산만 한다면 Thread 1이 counter 변수 값을 증가시켜도 CPU Cache에만 반영되어있어서 Main Memory에는 해당 내용이 없는 것이다. 그러니 Thread 2가 count 값을 읽어오면 증가된 값이 아니라 초기값이었던 0을 읽어오는 문제가 발생하는 것이다. 그래서 값 불일치 문제가 발생하는 것이다. 

 

그래서 해결 방법으로 volatile 키워드를 쓰는 것이다. 

 

volatile은 아래와 같이 사용하면 된다. 

public class SharedObject {
    public volatile int counter = 0;
}

 

이렇게 사용하면 Main Memory에 저장하고 읽어오기 때문에 변수 값 불일치 문제를 해결할 수 있다고 한다. 

 

그래서 Multi Thread 환경에서 하나의 Thread만 read와 write를 하고 나머지 Thread는 모두 read 를 한다면 volatile 키워드를 쓰는 것이 Main Memory에 써버리는 것이기 때문에 가장 최신의 값을 가져오는 것을 보장한다고 할 수 있다. 

 

다만 volatile 은 항상 올바르게 작동함을 보장하지는 않는다. 

만약 여러 Thread가 write 하는 상황이 존재한다면 그 상황에서는 최신의 값을 보장해주지 못한다. Thread 1이 counter 변수를 1만큼 증가시켜 1이 된 상황인데 아직 Main Memory에 반영하지 못했고 Thread 2가 counter 변수를 1만큼 증가시켜 1이 된 상황인데 아직 Main Memory에 반영하지 못했다면 각각의 결과를 Main Memory에 반영해서 결국 counter 변수 값이 1이 되는 상황이 발생한다. 원래대로라면 Main Memory의 counter 변수 값은 2가 되어야 정상이지만 1이 반영되는 문제가 생기는 것이다. 그 이유는 여러 Thread가 write를 하려고 했기 때문이다. 

 

그래서 여러 Thread가 write하는 상황이라면 synchronized 키워드를 통해서 변수 read와 write의 원자성 즉 atomic 함을 보장해야만 하는 것이다. 

 

volatile은 성능에 영향을 준다. 

왜냐하면 volatile 은 변수의 read와 write를 Main Memory 상에서 진행하기 때문이다. 

 

CPU Cache 보다 Main Memory가 비용이 더 크기 때문에 변수 값 일치를 보장해야만 하는 경우에만 volatile을 써야하고 나머지 경우에는 쓰지 않는 것이 좋다고 한다. 


아래 블로그에서 도움을 받았습니다. 

 

감사합니다. 

 

https://jenkov.com/tutorials/java-concurrency/volatile.html

 

velog.io/@godkimchichi/Java-6-Thread-%EA%B3%B5%EC%9C%A0%EA%B0%9D%EC%B2%B4-volatile

 

Java - 6. Thread: 공유객체, volatile

200923 공유객체, volatile

velog.io

 

 

nesoy.github.io/articles/2018-06/Java-volatile

 

Java volatile이란?

 

nesoy.github.io

 

반응형