[자바/동시성] CAS와 Atomic 클래스

자바에서 기본적으로 래퍼(wrapper) 클래스는 불변(immutable)이다. 래퍼 클래스를 한 번 인스턴스화 한 이후에는 값을 변경할 수 없다. 래퍼 클래스를 메서드의 파라미터나 메서드 블록의 로컬 변수로 선언하여 사용하는 경우 불변성에 대해서만 주의하면 사용에 큰 문제가 되지 않는다.

동시성 프로그래밍에서 공유 객체의 인스턴스 변수로 선언하여 사용할 가변 객체가 필요한 경우 불변의 래퍼 클래스를 사용할 수 없다. 원시 타입을 그대로 사용할 경우 동시성으로 인한 문제가 발생 가능하며 이를 해결하기 위해 동기화(synchronization)가 필요하다.

동시성 프로그래밍에서 서로 다른 스레드가 공유 객체의 데이터를 변경할 경우 연산이 원자적으로 수행되는 것이 의도될 수 있다. 간단하게는 synchronized 키워드를 사용하여 메서드나 코드 블록을 동기화하면 한 번에 하나의 스레드만 동기화된 블록에 접근할 수 있다. 하지만 이러한 동기화는 스레드를 블로킹(blocking)하며 연산 작업이 오래 걸리는 경우 시스템의 성능 저하를 일으키게 되므로 주의해야 한다.

CAS(compare-and-swap)는 동시성 프로그래밍에서 동기화로 인한 스레드 블로킹의 문제를 해결하는 기법이다. CAS를 사용하면 스레드를 블로킹하지 않고 동기화를 수행하여 스레드 안전하게 공유 객체의 값을 변경할 수 있다.

자바는 java.util.concurrent.atomic 패키지를 통해 Atomic으로 시작하는 가변(mutalble) 래퍼 클래스를 제공한다. Atomic 래퍼 클래스는 CAS를 구현한다. 구체적으로는 Atomic 클래스의 compareAndSet() 메서드가 그 역할을 수행한다. Atomic 래퍼 클래스는 인스턴스의 값을 원자적(atomic)으로 변경할 수 있도록 한다. Atomic 래퍼 클래스는 불변 래퍼 클래스를 대체하는 용도로 사용할 수 없으며 동시성(concurrency) 프로그래밍에서 스레드 논블로킹(non-blocking)을 구현하는 것과 같이 원자적 연산(atomic operation)이 필요한 상황에서만 제한적으로 사용되어야 한다.


참고

Comments