728x90
반응형
Java
에서synchronized
키워드는 멀티스레드 환경에서 공유 자원에 대한 동기화(Synchronization
) 를 제공하여 데이터 일관성 유지 및 경쟁 상태(Race Condition
) 방지 에 사용됩니다.
메서드 전체를 동기화할 때 사용합니다.
- 인스턴스 메서드 → 해당 객체(
this
)에 대한 잠금(Lock) 을 가짐 - 정적 메서드 → 클래스(
Class
)에 대한 잠금(Lock) 을 가짐
java
class SharedResource {
public synchronized void syncMethod() {
System.out.println(Thread.currentThread().getName() + " 실행 중");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName() + " 종료");
}
}
- 같은 객체에서
syncMethod()
를 여러 스레드가 호출하면, 한 번에 하나의 스레드만 실행됨.
java
class SharedResource {
public static synchronized void staticSyncMethod() {
System.out.println(Thread.currentThread().getName() + " 실행 중");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName() + " 종료");
}
}
- 정적 메서드는 클래스 레벨(Class-wide)에서 동기화되므로, 같은 클래스 내의 모든 객체에 영향을 줌.
메서드 전체가 아니라 특정 코드 블록만 동기화하여 불필요한 성능 저하 방지.
java
class SharedResource {
public void syncBlock() {
System.out.println(Thread.currentThread().getName() + " 실행 중 (동기화 X)");
synchronized (this) { // 특정 객체(this)만 동기화
System.out.println(Thread.currentThread().getName() + " 동기화 블록 진입");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName() + " 동기화 블록 종료");
}
System.out.println(Thread.currentThread().getName() + " 실행 종료 (동기화 X)");
}
}
synchronized (this)
는 현재 객체에 대한 락(Lock) 을 사용.
java
class SharedResource {
private final Object lock = new Object();
public void syncBlock() {
synchronized (lock) { // 특정 객체 lock을 동기화 대상으로 설정
System.out.println(Thread.currentThread().getName() + " 실행 중");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
System.out.println(Thread.currentThread().getName() + " 종료");
}
}
}
- 커스텀 락 객체(
lock
)을 사용하면 더 세밀한 동기화가 가능.
- 성능 저하: synchronized는 락을 얻기 위해 대기하는 시간이 필요함.
- 데드락(Deadlock) 위험: 여러 개의 synchronized 블록이 서로 다른 객체를 잠금하면 교착 상태가 발생 가능.
synchronized
보다 유연한 제어 가능.tryLock()
을 활용하여 데드락 방지.
java
import java.util.concurrent.locks.ReentrantLock;
class SharedResource {
private final ReentrantLock lock = new ReentrantLock();
public void safeMethod() {
if (lock.tryLock()) { // 락 획득 시도 (데드락 방지)
try {
System.out.println(Thread.currentThread().getName() + " 실행 중");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 락 해제
}
} else {
System.out.println(Thread.currentThread().getName() + "은 락을 얻지 못함");
}
}
}
tryLock()
은 즉시 락을 얻을 수 없으면 대기하지 않고 바로 반환하여 데드락을 방지.
사용 방식 | 설명 |
---|---|
synchronized method |
전체 메서드를 동기화 (객체 또는 클래스 락) |
synchronized block |
특정 코드 블록만 동기화 (더 효율적) |
ReentrantLock |
더 유연한 동기화 (tryLock 가능) |
- 🚀
synchronized
는 간단하지만, 성능을 고려하면ReentrantLock
같은 대안도 필요!
728x90
반응형
'Java' 카테고리의 다른 글
자바 어노테이션 (Java Annotation) 목록 (0) | 2025.03.14 |
---|---|
하위 버전 JAVA로 컴파일 하기 (0) | 2025.01.09 |
JDK 버전과 Class File Version의 관계 및 확인 방법 (0) | 2024.12.16 |
자바(Java) 바이트코드 파일(.class) 명명 규칙 (0) | 2024.12.11 |
eclipse 루나 + openJDK 1.8 (0) | 2024.11.21 |