Atomic Type은 단일 변수에 대해서 Atomic Operations을 지원한다.
Wrapping 클래스의 일종으로, 참조 타입과 원시 타입 두 종류의 변수에 모두 적용이 가능하다. 사용시 내부적으로 Compare -And-Swap 알고리즘?을 사용해 lock 없이 동기화 처리를 할 수 있다.
class MyLock {
private var locked = false
fun tryLock(): Boolean {
// 강제로 비용이 큰 작업 발생
for (i in 1..100_000) {}
if (!locked) {
locked = true
return true
}
return false
}
}
class TestRunnable(private val myLock: MyLock): Runnable {
override fun run() {
println("${Thread.currentThread().name}-${mylock.tryLock()}")
}
}
fun main() {
val myLock = MyLock()
for (i in 1..100_000) {
Thread(TestRunnable(myLock)).start()
}
}

위 코드를 실행해 보면 true와 false가 섞여 있는 것을 볼 수 있다. 여기서 원자성을 보장하고 싶다면 boolean 타입을 AtomicBoolean으로 바꾸기만 하면 된다.
class MyLock {
private val locked = AtomicBoolean()
fun tryLock(): Boolean {
if (!locked.get()) {
// 강제로 비용이 큰 작업 발생
for (i in 1..100_000) {}
}
return locked.compareAndSet(false, true)
}
}

처음 접근한 쓰레드를 제외하곤 모두 락을 획득하지 못해 false가 리턴되는걸 볼 수 있다.
CAS 알고리즘은 현재 주어진 값(현재 쓰레드에서의 데이터)과 실제 모리 데이터를 비교해서 두 개가 일치할 때만 값을 업데이트 한다고 한다. 이 역할을 하는 메소드가 compareAndSet() 이다. 즉 synchronized 처럼 임계영역에 같은 시점에 두개 이상의 쓰레드가 접근하려 하면 쓰레드 자체를 blocking 시키는 알고리즘이다.
