logo

English

이곳의 프로그래밍관련 정보와 소스는 마음대로 활용하셔도 좋습니다. 다만 쓰시기 전에 통보 정도는 해주시는 것이 예의 일것 같습니다. 질문이나 오류 수정은 siseong@gmail.com 으로 주세요. 감사합니다.

atomic vs volatile vs synchronized

by 엉뚱도마뱀 posted Dec 18, 2017
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print Attachment
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print Attachment

 이번 글은 java에서의 동기화 방법에 대해 다뤄본다.

글에 앞서 관련 글을 읽어오길 바란다. Atomic Operation

 

 

 private int counter;

 public int getNextUniqueIndex() {

   return counter++; 

}

 

위 코드는 관련 글에서도 다뤘다.

메모리에서 counter 변수를 읽은 후 값을 증가시키고 다시 메모리에 저장하는 작업 3가지로 분리된다.

싱글 스레드에서는 문제가 되지 않지만, 멀티 스레드에서는 문제가 된다. (위 관련 글에서 자세히 볼 수 있다)

문제로는 경쟁 상태와 변수의 가시성 문제가 발생한다.

* 경쟁 상태(race condition) 

  - 여러 스레드 같은 시점 변수를 읽는 상태.

* 변수의 가시성(visibility)

  - 변수들이 사용될 수 있는 영역의 범위

 

변수의 가시성 문제는 아래와 같다.

변수의 값은 CPU 메모리와 메인 메모리에 저장된다.

이 값을 CPU 메모리인지 메인 메모리에서 가져오는 지 알 수가 없다는 문제가 변수의 가시성 문제이다.

아래 메모리 구조를 보면 이해하길 바란다.

 

21166D4E588D52070F8983.png

 

 

이렇게 CPU 메모리에서 값을 읽어들인다면 매우 안전하지 못한다.

그래서 동기화 방식을 스레드 자체만으로 해결하는 방식은 아래와 같다.

일반적인 스레드 중단 방식1  

일반적인 스레드 중단 방식2

 

이번에는 AtomicInteger 을 보자.

 

 private AtomicInteger counter = new AtomicInteger();

 public int getNextUniqueIndex() {

   return counter.getAndIncrement();

}

 

AtomicInteger 클래스는 CAS(compare-and-swap) 기반으로 되어있다.

CAS란 특정 메모리 위치의 값이 주어진 값을 비교하여 같으면 새로운 값으로 대체된다.

CAS를 c언어의 코드로 보면 쉽게 이해가 갈 것이다.

 

int compare_and_swap(int* reg, int oldval, int newval)

{

  int old_reg_val = *reg;

  if (old_reg_val == oldval)

     *reg = newval;

  return old_reg_val;

}

 

위와 같은 흐름으로 이해하면 된다.

Atomic***** 관련 클래스는 이러한 흐름의 CAS를 기반으로 동작한다.

Java를 보자면 아래와 같다.

 

int current;

do {

  current = get();

} while(!compareAndSet(current, current + 1));

 

기본적으로 비교하는 과정에서 실패한다면 다시 읽고 비교하고 반복하는 과정을 가진다. (compareAndSet는 네이티브 메소드이다)
 
이번에는 volatile을 보자.
 
private volatile int counter;
 
public int getNextUniqueIndex() {
   return counter++;
}
 

volatile 키워드를 변수 앞에 선언하여 사용할 수 있다.

이로써 가시성 문제를 해결할 수 있다.

volatile은 어떠한  역할을 하는 것인가? 살펴보자.

위의 메모리 구조에서 보듯 CPU 메모리와 메인 메모리를 사용하고 있다.

하지만 volatile을 사용한다면 counter 변수를 읽고 쓰는 과정은 모든 읽기 쓰기 연산을 메인 메모리에서만 처리된다.

이로써 변수의 가시성 문제를 해결할 수 있게 되는 것이다.

 

하지만 가시성 문제는 해결했지만, 여전히 경쟁 상태 문제가 발생한다.

메인 메모리만을 이용한다하더라도 동시에 변수를 읽어들이는 상황은 발생하기 때문이다.

 

마지막으로 synchronized 를 알아보자.

가장 많이 알고 있는 동기화 방법이라고 생각한다.

간단히 말하자면, 하나의 스레드가 lock을 얻어 수행이 끝날때까지 다른 스레드들은 lock 풀릴때까지 대기하게 된다.

 

private Integer i = 0;

synchronized(i) {

  i++;

}

 

Java의 동기화 방법 3가지에 대해 알아보았다.

정리하여 언제 쓰일 수 있는 지는 아래와 같다.

 

volatile의 경우는 하나의 스레드가 쓰기 연산을 하고, 다른 스레드에서는 읽기 연산을 통해 최신 값을 가져올 경우. 즉 다른 스레드에서는 업데이트를 행하지 않을 경우 이용할 수 있다.

 

Atomic*** 클래스의 경우는 여러 스레드에서 읽기 쓰기 모두 이용할 수 있다. (CAS)

 

synchronized 경우도 여러 스레드에서 읽기 쓰기 모두 이용할 수 있다. (Lock)

 

목적은 비슷할지라도 내부적으로 완전히 다르기 때문에 내부를 이해하는 것이 큰 도움이 된다.

아래 링크인 stackoverflow의 글을 참고하여 번역하였다.

 

 

What is the difference between atomic / volatile / synchronized?

http://stackoverflow.com/questions/9749746/what-is-the-difference-between-atomic-volatile-synchronized

 

위키 Compare-and-swap

https://en.wikipedia.org/wiki/Compare-and-swap 

 

TAG •

List of Articles
No. Subject Author Date Views
22 Android - 블루투스 BLE 개발하기 digipine 2017.11.02 16881
21 Android - 슬립모드 (Sleep Mode) 방지 코드 digipine 2017.10.29 2563
20 안드로이드 파일 입출력시 한글 깨짐 문제 digipine 2017.10.29 1820
19 Android 하드웨어 코덱 포팅하기, OpenCore, OpenMAX digipine 2017.11.03 1769
18 [안드로이드] 가속도 (Accelerometer)센서 Shake 이벤트 예제 digipine 2017.11.02 1737
17 Ubuntu 리눅스 fastboot 설치 lizard2019 2019.12.13 1643
16 Toolchain Error 'No such file or directory' 해결방법 lizard2019 2019.12.19 1493
15 Android - 이미지(비트맵) 리사이징 digipine 2017.11.01 1466
14 안드로이드 Native C 코드에서 Intent 보내는 방법 digipine 2017.11.02 1441
13 Atomic Operation에 대해서 엉뚱도마뱀 2017.12.18 1352
12 안드로이드 시스템 개발시 mmm 커멘드 사용법 digipine 2017.11.01 1322
» atomic vs volatile vs synchronized file 엉뚱도마뱀 2017.12.18 1304
10 안드로이드 Activity간 인자 전달하기 digipine 2017.10.29 1164
9 Ubuntu 16.0.4 openjdk 7 설치방법 lizard2019 2019.12.19 962
8 [Java] SortedSet과 Comparable을 이용한 정렬(Sort) digipine 2017.10.29 904
7 Android 기반 Application Ant 빌드 방법 digipine 2017.10.29 866
6 Android - Browser 에서 Activity 실행하기 file digipine 2017.10.29 853
5 Ubuntu 기본 쉘 dash 대신 bash로 설정 digipine 2017.11.02 793
4 구글에서 제공하는 안드로이드 개발 기초 학습코스 file digipine 2022.03.18 577
3 안드로이드 애플리케이션 구성요소 digipine 2017.10.29 574
Board Pagination Prev 1 2 Next
/ 2