본문으로 건너뛰기
김신건의 로그

[Java] StampedLock

· 수정 · 📖 약 1분 · 391자/단어 #java #concurrent #lock #optimistic #read-write
StampedLock, java.util.concurrent.locks.StampedLock, 스탬프락, optimistic read

정의

java.util.concurrent.locks.StampedLock 는 JDK 1.8 도입의 새 락. 세 가지 모드 제공.

  1. Write lock (배타)
  2. Read lock (공유)
  3. Optimistic read (락 안 잡고 시도, 변경 감지 시 retry)

stamp 라는 long 토큰으로 락 상태를 추적. acquire 시 stamp 반환, release 시 stamp 전달.

시각화

핵심 메서드

StampedLock lock = new StampedLock();

long stamp = lock.writeLock();
try { ... } finally { lock.unlockWrite(stamp); }

long stamp = lock.readLock();
try { ... } finally { lock.unlockRead(stamp); }

// Optimistic read
long stamp = lock.tryOptimisticRead();
int value = data.get();                       // 락 없이 읽기
if (!lock.validate(stamp)) {                  // 변경 발생?
    stamp = lock.readLock();                  // 폴백: read lock
    try {
        value = data.get();
    } finally {
        lock.unlockRead(stamp);
    }
}

Optimistic Read 의 사상

writer 가 거의 없을 것이라 가정하고 락 없이 일단 읽는다. 끝나고 “내가 읽는 동안 write 가 있었나?” 를 validate(stamp) 로 검사. 없었다면 데이터가 일관, 있었다면 read lock 으로 폴백.

volatile read 한 번 정도의 비용으로 끝나는 best case.

사용 패턴

class Point {
    private double x, y;
    private final StampedLock lock = new StampedLock();

    public void move(double dx, double dy) {
        long stamp = lock.writeLock();
        try {
            x += dx;
            y += dy;
        } finally {
            lock.unlockWrite(stamp);
        }
    }

    public double distanceFromOrigin() {
        long stamp = lock.tryOptimisticRead();
        double cx = x, cy = y;                   // 락 없이 읽기
        if (!lock.validate(stamp)) {
            stamp = lock.readLock();
            try {
                cx = x; cy = y;
            } finally {
                lock.unlockRead(stamp);
            }
        }
        return Math.sqrt(cx * cx + cy * cy);
    }
}

Point 의 두 필드를 atomic 하게 읽기 위해 락 없이 시도 → 변경 발생 시 폴백.

제약사항

  • 재진입 불가. 같은 스레드가 두 번 write lock 잡으면 deadlock.
  • Condition 미지원. wait/notify 같은 조건 변수 사용 불가.
  • 인터럽트 처리 메서드별로 다름, 모두 인터럽트 응답하는 건 아님.
  • upgrading / downgrading 가능 (다른 stamp 발급).

언제 적절한가

읽기 압도적으로 많고, 쓰기는 거의 없으며, 짧은 읽기 인 경우. Point 처럼 두세 필드를 읽는 정도.

긴 read 작업이라면 optimistic read 도중 변경 발생 가능성이 높아 폴백 비용이 누적된다.

ReentrantReadWriteLock vs StampedLock

항목ReentrantReadWriteLockStampedLock
재진입
조건 변수
optimistic read
코드 복잡도단순복잡
성능 (read 99%)좋음더 좋음
성능 (read 50%)비슷비슷 또는 더 나쁨

참고

이 글의 용어 (4개)
[Java] ReentrantLockjava
정의 는 키워드와 같은 상호 배제 (mutual exclusion) 를 제공하는 클래스 기반 락. JSR-166 (Java 5) 에서 추가됐다. "재진입 (reentrant)" …
[Java] ReentrantReadWriteLockjava
정의 는 읽기 락과 쓰기 락을 분리 한 의 확장. 핵심 규칙: - 여러 reader 가 동시에 read lock 획득 가능 (병렬 읽기) - writer 는 배타적, write …
[Java] volatilejava
정의 은 Java 의 키워드. 필드에 붙이면 두 가지를 보장한다. 1. 가시성 (visibility): 한 스레드의 쓰기가 다른 모든 스레드에 즉시 보인다. CPU 캐시에 머무르…
Non-Blocking (논블로킹)concurrency
정의 Non-Blocking 은 호출이 결과를 기다리지 않고 즉시 반환 하는 실행 방식. 결과가 준비되지 않았다면 "아직 안 됐다" 라는 신호 ( , , , 등) 를 반환하고, …

이 개념을 다룬 위키 페이지 (1)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기