Programming/Process & Multi Threading

[Java] 자바 고유락(Intrinsic Lock)이란? (synchronized block)

dev.pudding 2023. 12. 17. 00:56
728x90

고유락(Intrinsic Lock)

Java에서 고유락(intrinsic lock)은  monitor lock 으로 불리기도 하며, 멀티스레드 환경에서 동기화를 달성하기 위해 사용되는 내부적인 잠금 매커니즘이다. 고유락은 객체당 단 하나만 부여되며, synchronized 키워드를 이용하여 여러 스레드를 동기화 시킬 수 있다.

 

사용예시는 다음과 같다.

public static int counter = 0; // 공유자원 

public synchronized void increment(){ // 고유락
	counter++;
}

public static void process(){
	
    Thread t1 = new Thread(new Runnable(){
    	@Override
        public void run(){
        	for(int i=0;i<10;i++){
            	increment();
            }
        }
    });
    
     Thread t2 = new Thread(new Runnable(){
    	@Override
        public void run(){
        	for(int i=0;i<10;i++){
            	increment();
            }
        }
    });
    
    //스레드 실행
    t1.start();
    t2.start();
    
    t1.join();
    t2.join();


}

 t1과 t2는 counter라는 공유자원에 동시에 접근하고 있지만 increment() 메소드는 synchronized 키워드로 인해 고유락에 묶여있기 때문에 오직 하나의 스레드만 공유자원에 접근이 가능하다. 따라서 프로그램을 안정적으로 실행할 수 있게 된다.

 

 

사용예시

하지만 위의 코드에는 약간의 문제점이 있다. 만약 한 개의 클래스에 두 개 이상의 synchronized 키워드를 가진 메소드가 정의되어 있다면 한 개의 메소드가 동기화 처리될 때 다른 메소드는 동기화 처리되지 않는다. 왜냐하면 고유락은 객체당 하나만 있기 때문에 특정 클래스의 synchronized 메소드가 실행되는 동안 해당 객체의 모든 다른 synchronized 메소드는 고유락을 사용할 수 없게 되어 동기화 처리가 되지 않는다. 이는 성능문제와 데드락(Deadlock)이 일어날 수 있어서 메소드 선언부에 synchronized 키워드를 사용하는 것은 피해야한다. 

 

이러한 문제점을 막기 위해서는 synchronized 키워드를 메소드 선언부에 사용하지 않고,  메소드 내부에  필요한 부분에만 사용해야한다. 

예시는 다음과 같다.

public class Example {
    private Object lock = new Object(); // 동기화에 사용될 객체

    public void synchronizedMethod1() {
        synchronized (lock) { // synchronized 키워드를 블록처리함 
            //  코드
        }
    }

    public void synchronizedMethod2() {
        synchronized (lock) { // synchronized 키워드를 블록처리함 
            // 코드
        }
    }
}

 

synchronized 키워드를 메소드의 선언부에 사용하는 것이 아니라, 메소드 내부에 synchronized블록을 사용하여 단일락으로서 사용하게 한다.  synchronized를 단일 블록으로 사용하게 되면 해당 블록 내에서만 동기화가 이루어지고 다른 synchronized 블록은 영향을 받지 않는다.