ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] volatile keyword
    Java 2021. 3. 7. 18:22
    반응형

     Java에서 volatile 키워드는 자바 변수가 컴퓨터 CPU Cache가 아닌, 메인 메모리에서 읽어올 수 있도록 합니다. 즉, volatile 키워드가 붙은 변수는 오직 메인 메모리에서만 데이터를 읽고 쓰게 되는 것입니다.

     

     이제부터 멀티쓰레드 환경에서 volatile 키워드가 가지는 의미에 대해서 알아보겠습니다.

    변수 가시성 문제

     멀티쓰레드 어플리케이션에서 각 쓰레드들이 non-volatile 변수들이 데이터에 접근할 때는 성능상의 이유로 메인 메모리로부터 읽고, CPU Cache에 복사해둡니다. 만약 컴퓨팅 환경이 두 개 이상의 CPU가 돌아간다면 아래의 이미지처럼 각자의 CPU에서 이러한 동작이 일어나게 될 것입니다.

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

      non-volatile 변수들은 언제 JVM이 메인 메모리에서 CPU Cache로 데이터를 읽어들일지, CPU Cache에서 메인 메모리르 데이터를 쓸 지 보장할 수 없습니다. 이러한 동작은 몇 가지 문제점들을 야기시킵니다.

     

    두 개 이상의 쓰레드가 하나의 공유 자원에 접근할 경우

    public class ShardObject {
        public int counter = 0;
    }

     위와 같이 공유 객체에 대한 non-volatile 변수 counter를 두 쓰레드에서 접근한다고 가정해 보겠습니다. 1번 쓰레드에서는 counter 변수를 증가시키고나서 2번 쓰레드가 couter 변수에 대해 접근한다면, 2번 쓰레드에서는 counter 변수가 7로 업데이트 된 사실을 알 수가 없습니다. 이는 non-volatile 변수 값이 CPU Cache에서 메인 메모리로 언제 쓰여질지 알 수 없기 때문입니다. 이를 가시성 문제라고 합니다.

    volatile 키워드를 통한 가시성 보장

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

     위와 같이 같은 공유 객체에 non-volatile 변수 대신에 volatile 키워드를 붙여서 사용할 경우 volatile 변수는 메인 메모리로 즉시 데이터를 쓰게 됩니다. 또한 counter 변수는 메인 메모리로부터 직접 읽게 됩니다.

     

     아까와 달라진 점은 1번 쓰레드가 counter 변수를 읽고, 다른 값으로 쓰고나서 2번 쓰레드가 counter 변수에 접근한다면 새롭게 변경된 counter 값을 읽을 수 있게 됩니다.

     

    volatile 키워드의 원자성 보장 문제

     volatile 키워드는 해당 변수가 메인 메모리로 직접 읽고 쓰는 것을 보장하지만 값에 대한 최신화가 언제나 보장되는 것은 아닙니다.

     1번 쓰레드에서 counter 값을 0으로 읽고, 값을 1 증가시키는 연산을 진행합니다. 1번 쓰레드의 값이 메인 메모리에 쓰여지기 전에 2번 쓰레드에서 counter 값(현재 0)을 읽고 마찬가지로 1 증가 시키는 연산을 진행합니다.

     1번 쓰레드에서 메인 메모리로 counter 값을 쓰고, 그 다음으로 2번 쓰레드에서도 메인 메모리로 값을 쓰게 됩니다. counter 값은 최종적으로 1이 됩니다.

     

     실제로는 counter 값이 2가 되어야하는 상황이지만 멀티쓰레드 환경에서 값을 동시에 접근하다보니 이러한 문제가 발생하게 됩니다.

     

     따라서 여러 쓰레드에서 값을 동시에 read/write 한다면 synchronized 키워드를 사용하여 값의 원자성을 보장해주어야 합니다.

     

    volatile의 성능 고려

     volatile 키워드를 사용하면 메인 메모리에서 직접 read/write 되므로 CPU Cache에서 접근하는 것보다 많은 비용이 발생한다는 점을 고려해야 합니다.

     


    참고자료

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

     

    Java Volatile Keyword

    The Java volatile keyword guarantees variable visibility across threads, meaning reads and writes are visible across threads.

    tutorials.jenkov.com

     

    반응형

    'Java' 카테고리의 다른 글

    [Java] Garbage Collector 이해하기  (0) 2020.10.04
    [Java] ThreadLocal이란?  (0) 2020.09.27
    [Java] JVM의 구조  (0) 2020.07.28
    [Java] 람다 표현식 (메서드 레퍼런스)  (1) 2019.12.22
    [Java] Image Resize 방법  (1) 2019.12.17

    댓글

Designed by Tistory.