본문 바로가기
language/java

synchronized 원리 완벽 이해하기

by 죄니안죄니 2026. 5. 29.
반응형

synchronized 원리 완벽 이해하기

지금부터가 진짜 멀티스레드의 시작입니다.

앞에서 배운:

프로세스
↓
스레드
↓
Heap 공유
 

때문에 발생하는 가장 대표적인 문제가 있습니다.

바로:

Race Condition (경쟁 상태)

입니다.

그리고 이 문제를 해결하기 위해 Java가 가장 먼저 제공한 것이:

synchronized

입니다.

실무 면접에서도:

synchronized 원리를 설명해주세요.
 

는 정말 자주 나오는 질문입니다.


대표 이미지

synchronized 원리
synchronized 원리synchronized 원리
 
 

 


1. Race Condition이란?

예:

 
public class Counter {

    int count = 0;

    public void increase() {
        count++;
    }
}
 

2. 스레드 2개가 동시에 실행

 
Thread A
Thread B
 

동시에:

 
count++;
 

실행.


3. 예상

10000번 증가
+
10000번 증가

=

20000
 

4. 실제

18342

19782

19901
 

등.

매번 다름.


5. 왜 그럴까?

count++ 는 사실 한 줄이 아닙니다.


6. JVM 관점

실제로는:

 
count++;
 

1. count 읽기

2. +1 계산

3. count 저장
 

7. 문제 상황

count = 5
 

Thread A

읽기 → 5
 

Thread B

읽기 → 5
 

Thread A

저장 → 6
 

Thread B

저장 → 6
 

결과

7이 되어야 하는데

6
 

8. 이것이 Race Condition

Race condition


9. 해결 방법

한 번에 한 스레드만 실행.


즉:

Thread A 실행 중

↓

Thread B 대기
 

10. synchronized 등장

예:

 
public synchronized void increase() {

    count++;
}
 

11. 의미

동시에 하나의 Thread만 진입 가능
 

12. 결과

Thread A
 ↓
작업
 ↓
종료

그 다음

Thread B
 

13. synchronized 내부 원리

매우 중요.


Java는

Monitor Lock
 

기반으로 동작.


14. Monitor란?

Monitor

한 줄 정의

객체가 가진 락(Lock)
 

15. 모든 객체는 락을 가진다

놀랍지만 사실.


예:

 
Object obj = new Object();
 

obj 내부

Object Header
 ↓
Monitor 정보
 

존재.


16. synchronized 메서드

 
public synchronized void increase()
 

실제로는

this Monitor 획득
 ↓
메서드 실행
 ↓
Monitor 반환
 

17. 그림으로 보면

Thread A
 ↓
Lock 획득
 ↓
실행
 ↓
Lock 해제

Thread B
 ↓
대기
 

18. synchronized 블록

메서드 전체 말고

일부만 가능.


 
public void increase() {

    synchronized(this) {

        count++;
    }
}
 

19. 의미

synchronized 영역만 보호
 

20. Lock 대상

매우 중요.


 
synchronized(this)
 

현재 객체 락
 

21. 다른 객체 사용 가능

 
private final Object lock =
        new Object();
 

 
synchronized(lock) {

}
 

22. 왜 별도 Lock 객체 사용?

실무에서 많이 사용.


 
synchronized(this)
 

외부 코드도 락 가능.


 
synchronized(lock)
 

내부 전용.


23. synchronized는 재진입 가능

매우 중요.


예:

 
public synchronized void a() {

    b();
}

public synchronized void b() {

}
 

24. 데드락 안 걸림

왜?


같은 Thread는

이미 락 보유 중.


25. 이것을

Reentrant Lock
 

이라고 함.


26. synchronized는 공정할까?

아니오.


예:

A 대기

B 대기

C 대기
 

반드시

A
↓
B
↓
C
 

순서 아님.


JVM이 결정.


27. synchronized의 단점

성능 비용

락 획득 필요.


Context Switch 증가

대기
↓
깨움
 

비용 발생.


병렬성 감소

동시에 실행 불가.


28. 그래서 최소 범위 권장

안 좋은 예

 
public synchronized void process() {

    DB조회

    API호출

    파일저장
}
 

29. 좋은 예

 
public void process() {

    synchronized(lock) {

        count++;
    }

    API 호출
}
 

락 범위를 최소화.


30. synchronized 내부 최적화

JDK 6 이후

많은 최적화 추가.


31. Biased Lock

예전 JVM 최적화.


아이디어

항상 같은 Thread만 사용
 

이면

락 검사를 생략.


※ JDK 15 이후 사실상 제거 수순.


32. Lightweight Lock

경쟁 적을 때.


OS Mutex 사용 안 함.


CAS 기반 처리.


33. Heavyweight Lock

경쟁 심함.


OS 수준 락 사용.


Context Switch 발생.


34. JVM 내부 흐름

Biased
 ↓
Lightweight
 ↓
Heavyweight
 

점점 무거워짐.


35. synchronized는 언제 필요할까?

대표:

공유 변수 수정
 

공유 컬렉션 수정
 

상태 변경
 

36. 필요 없는 경우

지역 변수.


 
public void test() {

    int x = 0;
}
 

지역 변수는

Stack
 

에 존재.


스레드 공유 안 함.


37. 면접 단골 질문

Q. synchronized는 무엇을 보호하나요?

Critical Section
 

Q. Lock은 어디에 있나요?

객체 Monitor
 

Q. synchronized(this) 의미는?

현재 객체 락 획득
 

Q. synchronized는 재진입 가능한가?

가능

(Reentrant)
 

Q. synchronized는 공정한가?

아니오
 

38. Critical Section

매우 중요.


한 줄 정의.

동시에 실행되면 안 되는 코드 영역
 

예:

 
count++;
 

대표적인 Critical Section.


39. 핵심 흐름 요약

여러 Thread
 ↓
공유 Heap 접근
 ↓
Race Condition 발생
 ↓
synchronized
 ↓
Monitor Lock 획득
 ↓
한 Thread만 실행
 ↓
Lock 반환
 

40. 가장 중요한 핵심 한 줄

synchronized는 객체의 Monitor Lock을 이용해 Critical Section에 한 번에 하나의 스레드만 진입하도록 보장하는 Java의 기본 동기화 메커니즘이다.
 

41. 실무에서 반드시 알아야 할 다음 단계

synchronized를 이해했다면 바로 다음에 나오는 질문이 있습니다.

그런데 count 값을 읽기만 할 때도 synchronized가 필요할까?
 

여기서 등장하는 것이:

volatile 키워드

입니다.

다음 글에서는:

  • CPU Cache
  • Memory Visibility
  • Cache Coherency
  • Happens-Before

까지 포함해서

volatile 키워드를 깊게 설명하겠습니다.

반응형

댓글