Java의 멀티스레딩 환경에서 동기화는 필수적입니다. 오늘은 Java의 고유락에 대해 깊게 알아보자
Java에서의 고유락은 모든 객체가 갖고 있는 내장 락을 지칭한다다. synchronized 키워드를 사용하여 이 락을 활용하면, 여러 스레드가 동시에 데이터에 액세스하는 것을 방지할 수 있다.
동기화된 메소드:
public synchronized void myMethod() {
// synchronized block of code
}
위와 같이 synchronized 키워드를 메소드 선언에 추가하면, 해당 메소드는 동기화 된다.
동기화된 블록: 특정 코드 부분만 동기화하려면 아래와 같이 사용한다.
synchronized(someObject) {
// synchronized block of code
}
예제:
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
위의 예제에서 increment() 메소드는 synchronized로 선언되었기 때문에 한 번에 한 스레드만이 이 메소드에 접근 가능하다.
재진입 가능: 이미 획득한 락을 다시 획득하는 것이 가능합니다. 이 특성은 재귀적인 동기화된 메소드 호출에 유용하다.
예제:
public synchronized void recursiveMethod(int value) {
if (value <= 0) return;
recursiveMethod(value - 1);
}
위의 예제에서 recursiveMethod는 동기화되어 있지만, 재진입성 덕분에 재귀 호출이 가능하다.
락의 해제: synchronized 메소드나 블록을 벗어나면 자동으로 락이 해제됩니다.
데드락: 여러 스레드가 서로의 락을 기다리면서 진행이 멈출 수 있다. 이를 데드락이라고 한다.
예제:
Object lock1 = new Object();
Object lock2 = new Object();
Thread thread1 = new Thread(() -> {
synchronized(lock1) {
synchronized(lock2) {
System.out.println("Thread 1");
}
}
});
Thread thread2 = new Thread(() -> {
synchronized(lock2) {
synchronized(lock1) {
System.out.println("Thread 2");
}
}
});
thread1.start();
thread2.start();
위의 예제에서 thread1과 thread2는 서로의 락을 기다리면서 데드락 상태에 빠질 수 있다.
과도한 동기화: 불필요한 동기화는 성능 저하를 초래할 수 있습니다. 동기화가 필요한 부분만 동기화하는 것이 중요합니다.
Java의 고유락은 멀티스레딩 환경에서 데이터의 일관성을 보장하는데 중요한 도구입니다. 그러나 적절하게 사용되지 않으면 문제점을 초래할 수 있으므로 신중하게 사용해야 합니다.