요점정리/자바 병렬 프로그래밍 Java Concurrency in Practice

03. 객체 공유

dextto™ 2014. 9. 2. 21:10


제목: (멀티 코어를 100% 활용하는) 자바 병렬 프로그래밍 / Java Concurrency in Practice

저자: 브라이어 게츠, 더그 리, 팀 피얼스, 조셉 보우비어, 데이빗 홈즈, 조슈아 블로쉬

출판사: 에이콘


3.1.2 단일하지 않은 64비트 연산

64비트를 지원하지 않는 JVM에서 64비트를 사용하는 숫자형(double, long 등)을 사용하는 경우 동시에 여러 스레드가 같은 변수값을 읽고 쓴다면 엉뚱한 값을 가져올 수 있음. 32비트 단위로 메모리에서 fetch/store하기 때문.


3.1.4 volatile 변수

volatile 변수: 메모리 가시성(Memory Visiblity, 한 Thread에서 변경한 특정 메모리의 값이, 다른 Thread에서 제대로 읽어지는지가)을 보장하기 위한 키워드

--> synchronized 블럭으로 처리한 것과 유사하지만, 의미가 명확하지 않아 읽기 어렵고 따라서 오류가 발생할 가능성이 있다.

--> 증가연산자(++)를 사용한 부분은 동기화를 맞춰주지 않는다.


volatile 변수는 다음과 같은 상황에서만 사용하는 것이 좋다.

  • 변수에 값을 저장하는 작업이 해당 변수의 현재 값과 관련이 없거나, 해당 변수의 값을 변경하는 쓰레드가 하나만 존재할 때

  • 해당 변수가 객체의 불변조건을 이루는 다른 변수와 달리 불변조건에 관련되어 있지 않을 때

  • 해당 변수를 사용하는 동안에는 어떤 경우라도 락을 걸어 둘 필요가 없는 경우


대표적인 사용예: 간단한 상태 체크

 
올바르게 생성자가 실행된 객체는 다음과 같은 방법으로 안전하게 공개할 수 있다.
  • 객체에 대한 참조를 static 메소드에서 초기화시킨다.
  • 객체에 대한 참조를 volatile 변수 또는 AtomicReference 클래스에 보관
  • 객체에 대한 참조를 올바르게 생성된 클래스 내부의 final 변수에 보관
  • 락을 사용해 올바르게 막혀 있는 변수에 객체 참조를 보관한다.
    ex) Vector나 synchronizedList 메소드 등과 같은 동기화된 컬렉션을 생성

여러 쓰레드를 동시에 사용하는 병렬 프로그램에서 객체를 공유해 사용하고자 할 때 가장 많이 사용되는 몇가지 원칙을 살펴보면 다음과 같다.

쓰레드 한정: 쓰레드에 한정된 객체는 완전하게 해당 쓰레드 내부에 존재하면서도 그 쓰레드에서만 호출해 사용할 수 있다.

읽기 전용 객체를 공유: 읽기 전용 객체를 공유해 사용한다면 동기화 작업을 하지 않더라도 여러 쓰레드에서 언제든지 마음껏 값을 읽어 사용할 수 있다. 물론 읽기 전용이기 때문에 값이 변경될 수는 없다. 불변객체와 결과적으로 불변인 객체가 읽기 전용 객체에 해당한다고 볼 수 있다.

쓰레드에 안전한 객체를 공유: 쓰레드에 안전한 객체는 객체 내부적으로 필수적인 동기화 기능이 만들어져 있기 때문에 외부에서 동기화를 신경쓸 필요가 없고, 여러 쓰레드에서 마음껏 호출해 사용할 수 있다.
동기화 방법 적용: 특정 객체에 동기화 방법을 적용해두면 지정한 락을 획득하기 전에는 해당 객체를 사용할 수 없다. 쓰레드에 안전한 객체 내부에서 사용하는 객체나 공개된 객체 가운데 특정 락을 확보해야 사용할 수 있도록 막혀 있는 객체 등에 동기화 방법이 적용되어 있다고 볼 수 있다.



반응형