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

자바(Java) 객체 수준 잠금 vs 클래스 수준 잠금: 차이점 완벽 정리

멀티스레딩 환경에서 잠금(Lock)이 필요한 이유

멀티스레딩 환경에서는 두 개 이상의 스레드가 동시에 공유 자원에 접근할 수 있으며, 이로 인해 시스템이 일관성 없는 동작을 보일 위험이 있습니다. 자바(Java)는 이러한 문제를 방지하기 위해 잠금(Lock) 개념을 사용하여 공유 자원이나 객체에 대한 동시 접근을 제한합니다. 자바의 잠금은 크게 두 가지 수준으로 나눌 수 있습니다.

  • 객체 수준 잠금(Object Level Lock) : 비정적(non-static) 메서드나 코드 블록을 한 번에 오직 하나의 스레드만 접근하도록 제한하고 싶을 때 사용합니다.
  • 클래스 수준 잠금(Class Level Lock) : 런타임에 존재하는 해당 클래스의 모든 인스턴스 중 어느 것이라도, 여러 스레드가 synchronized 블록에 동시에 진입하지 못하도록 할 때 사용합니다. 정적(static) 데이터를 스레드 안전하게 만들 때 반드시 사용해야 합니다.

객체 수준 잠금과 클래스 수준 잠금 비교

번호구분객체 수준 잠금클래스 수준 잠금
1 기본 개념 비정적(non-static) 메서드나 코드 블록을 오직 하나의 스레드만 접근하도록 할 때 사용합니다. 런타임에 존재하는 모든 인스턴스에서 여러 스레드가 synchronized 블록에 진입하지 못하도록 할 때 사용합니다.
2 Static / Non-static 비정적(non-static) 데이터를 스레드 안전하게 만들 때 사용해야 합니다. 정적(static) 데이터를 스레드 안전하게 만들 때 사용해야 합니다.
3 잠금의 개수 해당 클래스의 모든 객체가 각각 자신만의 고유한 잠금을 가집니다. 인스턴스가 여러 개 존재하더라도, 클래스 객체(Class Object)에 대한 잠금은 항상 단 하나만 존재합니다.

잠금을 획득하는 방법

1. 객체 수준 잠금 획득

  • 인스턴스 메서드에 synchronized 키워드를 붙입니다.
  • 코드 블록 내에서 synchronized(this)를 사용합니다.

2. 클래스 수준 잠금 획득

  • 정적(static) 메서드에 synchronized 키워드를 붙입니다.
  • 코드 블록 내에서 synchronized(ClassName.class)를 사용합니다.

클래스 수준 잠금 예제

public class ClassLevelLockExample {
    public void classLevelLockMethod() {
        synchronized (ClassLevelLockExample.class) {
            //여기에 작업 코드를 작성합니다
        }
    }
}

위 예제처럼 ClassName.class를 대상으로 synchronized 블록을 작성하면, 해당 클래스의 어떤 인스턴스를 통해서 호출되더라도 동일한 클래스 잠금을 공유하게 됩니다.

객체 수준 잠금 예제

public class ObjectLevelLockExample {
    public void objectLevelLockMethod() {
        synchronized (this) {
            //여기에 작업 코드를 작성합니다
        }
    }
}

synchronized(this)를 사용하면 현재 인스턴스에 대한 잠금을 획득합니다. 따라서 서로 다른 인스턴스의 메서드는 서로 간섭 없이 병렬로 실행될 수 있습니다.

정리

두 잠금의 핵심 차이는 잠금의 범위입니다. 객체 수준 잠금은 인스턴스 단위로 동작하며 인스턴스마다 독립적인 잠금을 가지는 반면, 클래스 수준 잠금은 JVM당 클래스당 하나만 존재하므로 정적 데이터나 전역적으로 공유되는 자원을 보호할 때 적합합니다. 상황에 맞는 잠금 수준을 선택하면 불필요한 성능 저하 없이 스레드 안전성을 확보할 수 있습니다.