rnesw.blog
📖
spring

Spring Lock

2024.01.15

스프링 부트에서의 락(Lock) 개념 정리

스프링 부트에서 동시성 문제를 해결하려면 다양한 락(Lock) 기법을 사용할 수 있다. 여러 스레드가 동시에 같은 자원에 접근하려 할 때, 데이터가 엉키지 않도록 데이터 무결성을 보장하려면 락을 걸어야 한다. 스프링 부트는 자바에서 제공하는 기본 락 외에도 다양한 락을 사용할 수 있게 해준다.

1. 낙관적 락 (Optimistic Lock)

낙관적 락은 데이터 충돌 가능성이 낮을 때 사용하는 방식이다. 데이터에 버전 필드를 두고, 충돌이 발생하면 예외를 발생시킨다. 주로 읽기 작업이 빈번하고 충돌이 적은 경우에 적합하다.

  • 예시:
    @Version
    private int version;

2. 비관적 락 (Pessimistic Lock)

비관적 락은 충돌 가능성이 높을 때 사용하는 락이다. 자원에 접근하려는 순간 락을 걸어 다른 스레드가 접근하지 못하게 막는다.

  • 예시:
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    Product findProductForUpdate(Long id);

3. 베타락 (Read-Write Lock)

읽기와 쓰기를 구분해서 관리하는 베타락은 여러 스레드가 동시에 읽기 작업을 할 수 있도록 하되, 쓰기 작업이 발생하면 읽기와 쓰기를 모두 막아 데이터의 일관성을 유지한다.

  • 예시:
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    lock.readLock().lock(); // 읽기 락
    lock.writeLock().lock(); // 쓰기 락

4. Synchronized 키워드

synchronized는 자바에서 가장 기본적인 락이다. synchronized 블록을 사용하면 한 번에 한 스레드만 접근할 수 있게 한다.

  • 예시:
    public synchronized void incrementCounter() {
        counter++;
    }

5. ReentrantLock

synchronized보다 좀 더 유연한 방법으로, 재귀적으로 락을 걸 수 있고 타임아웃을 설정할 수도 있다.

  • 예시:
    private final ReentrantLock lock = new ReentrantLock();
    lock.lock(); // 락 획득
    lock.unlock(); // 락 해제

6. StampedLock

Java 8부터 도입된 이 락은 읽기 작업이 많은 환경에서 성능을 높이는 데 효과적이다. 낙관적 읽기와 쓰기 락을 함께 제공한다.

  • 예시:
    long stamp = lock.tryOptimisticRead();
    if (!lock.validate(stamp)) {
        stamp = lock.readLock();
    }
    lock.writeLock();

7. Semaphore (세마포어)

세마포어는 동시에 접근할 수 있는 스레드 수를 제한하는 방식이다. 예를 들어, 세 개의 스레드만 자원에 접근하도록 설정할 수 있다.

  • 예시:
    private final Semaphore semaphore = new Semaphore(3);
    semaphore.acquire(); // 자원 획득
    semaphore.release(); // 자원 반환

8. CountDownLatch

여러 스레드가 특정 작업을 모두 완료할 때까지 대기하게 하는 도구다. 모든 스레드가 완료되면 다음 단계로 넘어간다.

  • 예시:
    private final CountDownLatch latch = new CountDownLatch(3);
    latch.countDown(); // 작업 완료 시 호출
    latch.await(); // 모든 작업이 완료될 때까지 대기

9. CyclicBarrier

여러 스레드가 모두 특정 지점에 도달할 때까지 기다리게 하고, 동시에 다음 작업을 시작하게 만드는 락이다.

  • 예시:
    private final CyclicBarrier barrier = new CyclicBarrier(3);
    barrier.await(); // 3개의 스레드가 모두 도착할 때까지 대기

스프링 부트에서 제공하는 다양한 락 기법들은 동시성 문제를 해결하는 데 중요한 역할을 한다. 상황에 맞게 낙관적 락, 비관적 락, 베타락 등을 선택할 수 있으며, ReentrantLock, StampedLock, Semaphore 같은 자바의 기본 락 도구들도 함께 사용할 수 있다. 이를 잘 활용하면 스프링 부트 애플리케이션에서의 동시성 문제를 효과적으로 해결할 수 있다.

👇 도움이 되셨다면 👇

B

u

y

M

e

A

C

o

f

f

e

e

© Powered by eddie