ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java Multithreading] 원자적 연산과 volatile
    Java/Multi Threading 기초 2022. 11. 10. 16:09

    Java Multithreading

    멀티스레딩의 개념과 Java에서의 활용법을 공부하고 정리하는 시리즈입니다.


    오늘은 Java의 연산 중에서 원자성이 지켜지는 연산과 지켜지지 않는 연산을 알아보고, 비원자적 자원을 보호하는 키워드를 하나 알아보겠습니다.

    Java의 원자적 연산과 비원자적 연산

    원자적 연산의 종류는 간단합니다.

    • 레퍼런스의 쓰기 또는 읽기
    • 원시타입의 쓰기 또는 읽기(doublelong 제외)

    위에 적었듯이 레퍼런스를 할당하고 복사하는 모든 작업은 원자성이 보장됩니다. 원시타입 변수에 값을 쓰고 읽는 모든 작업도 마찬가지입니다. 간단하게 기억할 수 있겠죠.
    그럼 예외적인 경우만 잘 다뤄보면 될 것 같은데요. 원시타입 중에서도 왜 longdouble만 제외 되는 걸까요?

    32bit 안에서 할당이 이루어지는 다른 원시타입들과 다르게, longdouble로 정의된 변수는 64bit로 할당됩니다. 그리고 64bit를 쓰고 읽는 대개의 경우는 32bit씩 두 번의 연산으로 나누어 실행됩니다.
    만약 둘 이상의 스레드가 해당 변수에 읽고 쓰는 작업을 한다면, 한 스레드가 32bit를 읽는 동안 나머지 스레드는 나머지 32bit에 대해 쓰기를 실행할 수도 있는 것이죠. 이런 경우엔 읽기를 실행한 스레드는 잘못된 값을 읽어가게 될 것입니다.

    그런데 문제가...

    사실 아무리 간단한 프로그램이라고 하더라도 변수에 값을 쓰거나 읽는 것만으로 구현하기는 어렵다는 것을 알고 있습니다. 우리가 작성해야 하는 많은 코드는 사실 원자성을 보장받기가 어렵다는 것이죠. 😅
    그렇기 때문에 더 많은 것을 고려하면서 프로그램을 작성해야하는 것은 맞지만, 그렇다고 해서 모든 로직을 synchronized 블럭 안에 넣을 수는 없습니다. 만약 그렇게 구현한다면 싱글 스레드로 작동하는 프로그램보다 나을 게 없겠죠(오히려 성능이 떨어지고 비용은 많이 들게 될 겁니다).

    volatile : 원자성을 보장하기 위한 또 다른 접근

    Java는 이런 문제를 해결하기 위해서 volatile이라는 키워드를 제공합니다. 아래와 같이 필드에 사용할 수 있습니다.

    public class Test {
    
      public volatile long sharedValue;
    }

    volatile 필드가 원자성을 제공하는 자세한 원리에 대해서는 나중에 설명할 기회가 있기를 바랍니다. 지금 이 포스팅에서는 volatile이 어떻게 동작하는지에 대해서만 이야기 할게요.

    volatile은 해당 필드에 접근할 때 lock을 걸도록 합니다. 지정한 메서드나 지정한 블록에 thread-safe를 보장하는 synchronized와는 다르게요. 해당 필드의 접근에 대해서만 원자성을 보장합니다. 한 스레드가 하나의 long 변수의 32bit를 쓰는 도중에 다른 스레드가 나머지 32bit를 쓰거나 읽지 못하도록 하는 것이에요.

    그러므로 하나의 스레드가 sharedValue에 값을 쓰고, 나머지 스레드들은 값을 읽어가기만 하는 상황을 가정한다면, 필드에 volatile 키워드를 사용하는 것만으로 적절한 임계영역의 처리가 될 것입니다.
    하지만 여러 스레드가 동시에, sharedValue에 단순히 접근하는 것 이상의 여러 연산을 수행하게 된다면 동시성을 보장하지 못할 거에요.

    결론

    멀티스레드 프로그래밍의 모든 로직을 synchronized로 구현할 수는 없습니다. 또한 volatile 만으로는 thread-safe를 보장할 수 없습니다.
    그렇기 때문에 상황을 고려하여 각각 적절한 상황에 사용해야할 것입니다.

    아마도 다음 포스팅부터는 이러한 '상황 대응'에 대한 좀 더 자세한 이야기를 다루게 될 것 같네요. 지루한 글을 읽으시느라 고생하셨습니다. 감사합니다. 😄

    댓글

Designed by Tistory.