Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

자바 ReentrantLock과 Synchronized의 차이점 완벽 비교

멀티스레드 환경에서 여러 스레드가 공유 자원에 접근할 때 락(lock)을 거는 방법은 크게 두 가지가 있습니다. 하나는 ReentrantLock(또는 ReadWriteLock)을 사용하는 것이고, 다른 하나는 synchronized 메서드 또는 블록을 사용하는 것입니다.

ReentrantLock 클래스는 Java 5부터 java.util.concurrent 패키지에서 제공되기 시작했습니다. 이 클래스는 Lock 인터페이스의 구현체로, 자바 공식 문서에 따르면 Lock 인터페이스는 synchronized 메서드나 블록으로 얻을 수 있는 기능보다 더 폭넓은 락 연산을 지원합니다.

ReentrantLock vs Synchronized 주요 차이점

번호구분ReentrantLockSynchronized
1락 획득lock() 메서드를 호출하여 스레드가 공유 자원에 대한 락을 획득합니다.synchronized 키워드만 작성하면 락이 자동으로 획득됩니다.
2락 해제개발자가 반드시 finally 블록에서 unlock() 메서드를 직접 호출해야 합니다.임계 영역을 벗어나면 락이 암묵적으로(자동으로) 해제됩니다.
3인터럽트 가능 여부lockInterruptibly() 메서드를 사용하면 락을 기다리는 스레드를 인터럽트할 수 있습니다.락을 기다리는 스레드를 인터럽트할 방법이 없습니다.
4공정성(Fairness)생성자에 fairness 파라미터가 있으며, true로 설정하면 가장 오래 기다린 스레드에게 우선적으로 락이 부여됩니다.특정한 접근 순서를 보장하지 않습니다.
5락 해제 순서획득한 순서와 무관하게 어떤 순서로든 락을 해제할 수 있습니다.블록 구조에 따라 자동으로 해제되므로 개발자가 해제 순서를 임의로 조정할 수 없습니다.

ReentrantLock 예제

public class ReentrantLockExample implements Runnable {
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            lock.lock();
            // 공유 자원에 대한 작업 수행
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();  // 반드시 finally 블록에서 락 해제
        }
    }
}

Synchronized 예제

public class SynchronizedLockExample implements Runnable {
    @Override
    public void run() {
        synchronized (resource) {
            // 공유 자원에 대한 작업 수행
        }
    }
}

어떤 것을 선택해야 할까?

synchronized는 사용법이 간단하고 락 해제를 직접 관리할 필요가 없어 대부분의 일반적인 상황에 적합합니다. 반면, 락 획득에 타임아웃을 설정하거나, 대기 중 인터럽트에 대응해야 하거나, 공정한(fair) 락이 필요한 등 세밀한 동시성 제어가 요구되는 경우에는 ReentrantLock이 더 나은 선택입니다.