본문 바로가기
기타 개발 관련/안드로이드 개념 정리

안드로이드 - volatile 이란 무엇이고, 왜 필요할까?

by 번데기 개발자 2019. 2. 26.
반응형
volatile 키워드


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

즉 매번 변수의 값을 Read할 때마다 CPU cache에 저장된 값이 아닌 Main Memory에서 읽는 것입니다.

또한 변수의 값을 Write할 때마다 Main Memory에 까지 작성하는 것입니다.



왜 필요할까?







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

만약 MultiThread환경에서 Thread가 변수 값을 가져올때 각각의 CPU Cache에 저장된 값이 다르기 때문에 변수 값 불일치 문제가 생길 수 있습니다.



예제) 

예를 들어 SharedObject를 공유하는 두개의 Thread가 있을때

하나의 쓰레드에서는 더하는 연산을 2번째 쓰레드에서는 값을 읽기만 한다고 가정했을때 반영이 되지 않는 문제가 발생합니다.








해결방법


Volatile 키워드를 추가하게 되면 변수를 Main Memory에 저장하고 불러오기 때문에 변수 값 불일치 문제를 해결할 수 있습니다.







언제 적합할까?


Multi Thread 환경에서 하나의 Thread만 read&write 하고 나머지 Thread가 read하는 상황에서 적합합니다.

반면 여러 Thread가 write하는 상황에서는 synchronized를 통해 변수 read&write 의 원자성(atomic)을 보장해야 합니다.




항상 volatile이 옳을까?


Example

  • Thread-1이 값을 읽어 1을 추가하는 연산을 진행합니다.
    • 추가하는 연산을 했지만 아직 Main Memotry에 반영하기 전 상황입니다.
  • Thread-2이 값을 읽어 1을 추가하는 연산을 진행합니다.
    • 추가하는 연산을 했지만 아직 Main Memotry에 반영하기 전 상황입니다. 
  • 추가하는 연산을 하여 최종결과가 2가 되어야 하는 상황이지만?
    • 각각 결과를 Main Memory에 반영하게 된다면 1만 남는 상왕이 발생하게 됩니다.


  • 하나의 Thread가 아닌 여러 Thread가 Write하는 상황에서는 적합하지 않습니다.
  • 여러 Thread가 write하는 상황이라면
    • synchronized를 통해 변수 read&write의 원자성(automic)을 보장해야 합니다.



volatile 성능에 어떤 영향이 있을까?

  • volatile은 변수의 read와 wrtie를 Main Memory에서 진행하게 됩니다.
  • CPU Cache보다 Main Memory가 비용이 더 크기 때문에 변수 값 일치 를 보장해야 하는 경우에만 volatile을 사용하는 것이 좋습니다.



정리하면

  • volatile
    • Main Memory에 read&write를 보장하는 키워드
  • 상황
    • 하나의 Thread가 write하고 나머지 Thread가 읽는 상황인 경우
    • 변수의 값이 최신의 값으로 읽어와야 하는 경우
  • 주의할 점
    • 성능에 영향이 어느정도 영향을 줄 수 있는 Point라는 점




내가 생각한 부분


연산 로직이 멀티쓰레딩으로 구현이 되있을때 항상 최신의 값을 메인메모리에서 가져오기 위해 사용한다. 

하지만 Main Memory에 쓰기연산(Write)를 여러 쓰레드에서 해야할 경우 Synchronized를 구현해야 한다.

Cpu Cache보다 Main Memory가 비용이 더 크기 때문에 변수 값 일치를 보장해야 하는 경우에만 volatile을 사용하는 것이 좋다.



안드로이드에서 사용되는 예제 1개




이런식으로 전역적으로 사용되는 라이브러리가 있다고 가정해보자

그럴때 해당 라이브러리의  instance는 여러 쓰레드에서 읽기 작업이 일어나게 되고, 변수의 값이 항상 최신의 값으로 읽어와야된다.

그리고 클래스 객체를 생성할때는 synchronized를 사용하여 하나의 쓰레드에서만 읽기작업을 수행하도록 설정한다.

이런식으로 전역적으로 사용하는 class에서 (라이브러리틱하게 보이는 클래스) 위와 같이 사용되기도 한다. 








반응형