Java 잠금없는 동기화 처리 구현 Atomic 클래스
Atomic 클래스
java.util.concurrent.atomic
패키지에서는, 값의 대입/조회 처리를 하드웨어 레벨에서 원자적(Atomic)으로 실행하는 수단을 제공한다.
AtomicBoolean
AtomicInteger
AtomicIntegerArray
AtomicLong
AtomicLongArray
이러한 클래스를 이용하는 것으로, synchronized
한정자, ReentrantLock
클래스와 같이 락을 사용할 필요 없이, 처리를 동기화 시키는 것이 가능하게 된다.
각 클래스에서 사용할 수 있는 처리에는 다음과 같은 것이 있다.
Atomic 클래스의 주요 메소드
메서드 | 개요 | AtomicBoolean 사용 가능 여부 |
---|---|---|
get() |
현재 값 조회 | O |
getAndSet(newValue) |
현재의 값을 조회오고, 지정된 값을 설정 | O |
set(newValue) |
지정된 값 설정 | O |
getAndAdd(delta) |
지정된 값을 추가(조작 전의 값을 조회) | X |
addAndGet(delta) |
지정된 값을 추가(조작 후의 값을 조회) | X |
getAndDecrement() |
현재의 값을 1 감소(조작 전의 값을 조회) | X |
decrementAndGet() |
현재의 값을 1 감소(조작 후의 값을 조회) | X |
getAndIncrement() |
현재의 값을 1 인크리먼트(조작 전의 값을 조회) | X |
incrementAndGet() |
현재의 값을 1 인크리먼트(조작 후의 값을 조회) | X |
사용 예시
다음은 synchronized
한정자 사용한 예제(increment 메서드)을 AtomicInteger
클래스에서 다시 작성한 것이다. 표준 “i++” 연산은 원자적이지는 않지만 AtomicInteger#getAndIncrement
메서드는 원자적이므로, 값의 조회으로부터 증분, 다시 대입하는 과정에 다른 thread가 인터럽트 하지 않는다.
AtomicSample.java
package com.devkuma.basic.atomic;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicSample {
private AtomicInteger count = new AtomicInteger();
public static void main(String[] args) {
AtomicSample as = new AtomicSample();
as.execute();
}
public void execute() {
final int THREAD_MAX = 300000;
Thread[] ts = new Thread[THREAD_MAX];
for (int i = 0; i < THREAD_MAX; i++) {
ts[i] = new Thread(new MyThread(this));
ts[i].start();
}
for (int i = 0; i < THREAD_MAX; i++) {
try {
ts[i].join();
} catch (InterruptedException e) {
System.out.println(e);
}
}
System.out.println(count);
}
public void increment() {
count.getAndIncrement();
}
private static class MyThread implements Runnable {
private AtomicSample _counter;
public MyThread(AtomicSample counter) {
this._counter = counter;
}
@Override
public void run() {
_counter.increment();
}
}
}
실행 결과:
300000
최종 수정 : 2022-09-24