public void atomicInteger1() {
    AtomicInteger atomic = new AtomicInteger();
    System.out.println("value : " + atomic.get()); // 0

    AtomicInteger atomic2 = new AtomicInteger(10);
    System.out.println("value : " + atomic2.get()); // 10
}

Java에는 Concurrent 문제를 해결하는 데 3가지 방법이 있다.

  1. volatile 이용 
  2. Atomic 클래스 이용
  3. synchronized 이용
  • volatile
    • 왜 필요한가?
      • 각각의 컴퓨터에서 어플리케이션을 실행하면, 각 쓰레드는 main memory에서 읽어온 변수 값을 각 CPU의 Cache로 복사하여 읽는다.  
      • 각 쓰레드가 같은 java 변수값을 가져왔다고 쳐도, 쓰레드가 CPU Cache에 저장된 값을 변경하고 메모리에 제때 쓰지 않는다면 각 쓰레드에서 사용하는 변수값이 일치하지 않을 수가 있다.
        • 한 쓰레드는 해당 변수를 카운트하고, 다른 쓰레드는 해당 변수를 ++ 한다고 가정하면, 카운트하는 쓰레드는 CPU캐시에만 업데이트 된 값을 가져올 수 없다는 것. 
      • 변수의 가시성 문제를해결할수있다.
        • 가시성 문제
          • CPU 메모리와 Main 메모리 중에서 어디서 가져온 값인지 알 수 없다.
          • 여러 스레드에서 변수에 대한 변경 사항의 가시성을 보장 
    • volatile변수는 컴퓨터의 메인 메모리부터 read하고, 메인 메모리에 직접 write 한다. 
    • 어떻게 쓰는가?
private volatile int count = 0;
  • atomic
    • CAS(Compare and Swap) 방식 
      • 변수의 값을 변경하기 전에 기존의 값이 내가 예상하던 값과 같을 때만 새로운 값으로 할당
public void atomicInteger2() {
    AtomicInteger atomic = new AtomicInteger();
    System.out.println("value : " + atomic.get()); // 0

    atomic.set(100);
    System.out.println("value : " + atomic.get()); // 100
}
  • atomic vs volatile
    • volatile 키워드는 오직 한개의 쓰레드에서 쓰기 작업을 하고, 다른 쓰레드는 읽기작업만을 할 때 사용
    • AtomicBoolean, AtomicInteger는 여러 쓰레드에서 읽기/쓰기 작업을 병행할 수 있다.
  • synchronized

출처

https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html

https://rightnowdo.tistory.com/entry/JAVA-concurrent-programming-Visibility%EA%B0%80%EC%8B%9C%EC%84%B1

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

https://readystory.tistory.com/53

https://codechacha.com/ko/java-atomic-integer/

 

 

+ Recent posts