๐ JAVA 06 - Java Thread, synchronized, volatile, Atomic
Java Thread, synchronized, volatile, Atomic
ํ์ต ๋ชฉํ
์ด๋ฒ ์ฃผ์ ์ ํต์ฌ์ ๋จ์ํ:
โ๋ฉํฐ์ค๋ ๋๋ ๋์์ ์คํ๋๋คโ
์์ค์ด ์๋๋ค.
์ค๋ฌด์์๋ ๋ฐ๋์ ์๋๋ฅผ ์ค๋ช ํ ์ ์์ด์ผ ํ๋ค.
Race Condition์ ์ ๋ฐ์ํ๋๊ฐ?
synchronized๋ ์ ํํ ๋ฌด์์ ๋ณด์ฅํ๋๊ฐ?
volatile์ ์ ํ์ํ๊ฐ?
Atomic์ ์ด๋ป๊ฒ lock ์์ด ๋์ํ๋๊ฐ?
CAS๋ ์ ๋ฑ์ฅํ๋๊ฐ?
ThreadLocal์ ์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ ๋ฐํ๋๊ฐ?
์ด์ ํ๊ฒฝ์์ ๋์์ฑ ๋ฌธ์ ๋ ์ด๋ป๊ฒ ์ฅ์ ๊ฐ ๋๋๊ฐ?
์ฆ:
Java ๋์์ฑ ๋ชจ๋ธ๊ณผ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์์ฑ ๋ฌธ์
๋ฅผ ์ดํดํ๋ ๊ฒ์ด ํต์ฌ์ด๋ค.
๋จผ์ ๊ฐ์ฅ ์ค์ํ ๊ฐ๋
๋ฉํฐ์ค๋ ๋ ๋ฌธ์ ์ ํต์ฌ์:
โ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ ๊ทผโ
ํ๋ ๊ฒ์ด๋ค.
Thread๋?
Thread๋:
ํ๋ก์ธ์ค ๋ด๋ถ ์คํ ํ๋ฆ
์ด๋ค.
์:
graph TD
A[Process]
A --> B[Thread 1]
A --> C[Thread 2]
A --> D[Thread 3]
์ค์ํ ํน์ง
Thread๋ค์:
Heap ๊ณต์
Method Area ๊ณต์
ํ๋ค.
๋ฐ๋ฉด:
- Stack์ ๊ฐ๋ณ ๋ณด์
ํ๋ค.
์ ์ํํ๊ฐ?
Heap์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ค.
์ฆ:
graph TD
A[Thread 1]
--> D[Shared Heap]
B[Thread 2]
--> D
C[Thread 3]
--> D
๋์์ ๊ฐ์ ๊ฐ์ฒด ์ ๊ทผ ๊ฐ๋ฅ.
Race Condition
๊ฐ์ฅ ์ค์ํ ๊ฐ๋ .
Race Condition์:
์คํ ์์์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง๋ ๋ฌธ์
๋ค.
์์
1
count++;
๊ฒ๋ณด๊ธฐ์ 1์ค์ด๋ค.
ํ์ง๋ง ์ค์ CPU ์์ค์์๋:
1
2
3
1. ๊ฐ ์ฝ๊ธฐ
2. +1 ์ํ
3. ๋ค์ ์ ์ฅ
3๋จ๊ณ๋ค.
์ ๋ฌธ์ ์ธ๊ฐ?
์:
sequenceDiagram
Thread1->>Memory: count ์ฝ๊ธฐ (0)
Thread2->>Memory: count ์ฝ๊ธฐ (0)
Thread1->>Memory: 1 ์ ์ฅ
Thread2->>Memory: 1 ์ ์ฅ
๊ฒฐ๊ณผ:
1
2
์๋ ๊ธฐ๋๊ฐ = 2
์ค์ ๊ฒฐ๊ณผ = 1
์ฆ:
๋ฐ์ดํฐ ์ ์ค
๋ฐ์.
synchronized
Java ๊ธฐ๋ณธ ๋๊ธฐํ ๋ฐฉ์.
1
2
3
public synchronized void increase() {
count++;
}
synchronized ํต์ฌ
ํต์ฌ์:
โํ ๋ฒ์ ํ๋์ Thread๋ง ์ ๊ทผโ
์ด๋ค.
๋ด๋ถ ๋์
graph TD
A[Thread 1]
--> D[Monitor Lock]
B[Thread 2]
--> D
D --> E[Critical Section]
Monitor Lock์ด๋?
Java ๊ฐ์ฒด ๋ด๋ถ์๋:
1
Monitor
๋ผ๋ lock ๋ฉ์ปค๋์ฆ ์กด์ฌ.
synchronized๋ ์ด Monitor ์ฌ์ฉ.
synchronized๊ฐ ๋ณด์ฅํ๋ ๊ฒ
1. Mutual Exclusion
๋์ ์ ๊ทผ ๋ฐฉ์ง.
2. Memory Visibility
๋ณ๊ฒฝ ์ฌํญ ๋ฉ๋ชจ๋ฆฌ ๋๊ธฐํ.
์ด๊ฒ ๋งค์ฐ ์ค์ํ๋ค.
synchronized ๋ฌธ์ ์
1. Thread Blocking
lock ๊ธฐ๋ค๋ฆฌ๋ฉฐ ๋๊ธฐ.
2. Context Switching ๋น์ฉ
CPU overhead ๋ฐ์.
3. ์ฑ๋ฅ ์ ํ ๊ฐ๋ฅ
๊ฒฝ์ ์ฌํ๋ฉด throughput ๊ฐ์.
volatile
volatile์ ๋งค์ฐ ์์ฃผ ์คํด๋๋ค.
volatile ํต์ฌ
volatile์:
โ๋ณ์ ์ต์ ๊ฐ ๋ณด์ฅโ
์ด๋ค.
์ ํ์ํ๊ฐ?
CPU๋ ์ฑ๋ฅ ํฅ์์ ์ํด:
CPU Cache
Register Cache
์ฌ์ฉํ๋ค.
๋ฌธ์ ์ํฉ
graph TD
A[Main Memory]
B[CPU Cache Thread1]
C[CPU Cache Thread2]
B --> A
C --> A
Thread๋ง๋ค cache ๊ฐ ๋ค๋ฅผ ์ ์์.
์์
1
private boolean running = true;
Thread1:
1
2
while(running) {
}
Thread2:
1
running = false;
๋ฌธ์
Thread1์ด CPU cache ๊ฐ ๊ณ์ ๋ณผ ์ ์์.
์ฆ:
1
๋ฌดํ ๋ฃจํ ๊ฐ๋ฅ
volatile ์ฌ์ฉ
1
private volatile boolean running;
volatile์ด ๋ณด์ฅํ๋ ๊ฒ
1. Memory Visibility
์ต์ ๊ฐ ์ฝ๊ธฐ ๋ณด์ฅ.
volatile์ด ๋ณด์ฅํ์ง ์๋ ๊ฒ
Atomicity
์ด๊ฑฐ ์์ฒญ ์ค์ํ๋ค.
์ฆ ์ด๊ฑด ์ํํ๋ค
1
2
3
volatile int count;
count++;
์ฌ์ ํ race condition ๊ฐ๋ฅ.
์๋๋ฉด:
1
read โ modify โ write
๋ atomicํ์ง ์๋ค.
Atomic ํด๋์ค
๋ํ:
1
2
3
AtomicInteger
AtomicLong
AtomicReference
ํต์ฌ ์ฒ ํ
lock ์์ด ์์์ ์ฐ์ฐ ์ํ
์ด๋ค.
CAS(Compare And Swap)
Atomic ํต์ฌ ๋ฉ์ปค๋์ฆ.
CAS ๋์ ํ๋ฆ
graph TD
A[ํ์ฌ ๊ฐ ์ฝ๊ธฐ]
--> B{์์๊ฐ๊ณผ ๋์ผ?}
B -->|YES| C[๊ฐ ๋ณ๊ฒฝ]
B -->|NO| D[์ฌ์๋]
์์
1
2
3
4
AtomicInteger count =
new AtomicInteger();
count.incrementAndGet();
์ ๋น ๋ฅธ๊ฐ?
๊ธฐ์กด synchronized:
1
Thread Blocking
๋ฐ์.
CAS๋:
lock-free ๋ฐฉ์
๊ฐ๋ฅ.
CAS ๋ฌธ์ ์
1. Spin ๋ฌธ์
์คํจ ์ ๊ณ์ ์ฌ์๋.
CPU ์ฌ์ฉ๋ ์ฆ๊ฐ ๊ฐ๋ฅ.
2. ABA ๋ฌธ์
1
A โ B โ A
๋ณ๊ฒฝ๋ผ๋ ๊ฐ์ง ๋ชปํ ์ ์์.
synchronized vs Atomic
synchronized
์ฅ์ :
๊ตฌํ ๋จ์
๋ณต์กํ ๋๊ธฐํ ๊ฐ๋ฅ
๋จ์ :
- blocking ๋ฐ์
Atomic
์ฅ์ :
๋น ๋ฆ
lock-free
๋จ์ :
- ๋ณต์กํ ์ฐ์ฐ ํ๊ณ
ThreadLocal
์ค๋ฌด์์ ์์ฒญ ์ค์ํ๋ค.
ThreadLocal ํต์ฌ
Thread๋ง๋ค ๋ ๋ฆฝ ๋ณ์ ์ ๊ณต
์ด๋ค.
์์
1
2
ThreadLocal<User> local =
new ThreadLocal<>();
์ ์ฐ๋๊ฐ?
๋ํ:
์ฌ์ฉ์ ์ ๋ณด
Transaction Context
๋ก๊ทธ ์ถ์
์ธ์ฆ ์ ๋ณด
Spring์์๋ ๋ง์ด ์ฌ์ฉ
๋ํ:
SecurityContextHolder
TransactionSynchronizationManager
ThreadLocal ๊ตฌ์กฐ
graph TD
A[Thread 1]
--> B[ThreadLocalMap]
C[Thread 2]
--> D[ThreadLocalMap]
์ Memory Leak ๋ฐ์ํ๋?
ํต์ฌ:
Thread Pool ๋๋ฌธ
์ด๋ค.
๋ฌธ์ ์ํฉ
Thread Pool Thread๋:
1
์ฃฝ์ง ์๊ณ ์ฌ์ฌ์ฉ
๋๋ค.
๊ทธ๋ฐ๋ฐ remove ์ ํ๋ฉด?
1
threadLocal.set(user);
๋ง ํ๊ณ :
1
remove()
์ ํ๋ฉด ๊ฐ ๊ณ์ ๋จ๋๋ค.
๊ฒฐ๊ณผ
graph TD
A[Thread Pool Thread]
--> B[ThreadLocalMap]
B --> C[User Object]
๊ฐ์ฒด GC ์ ๋จ.
์ค์ ์ด์ ์ฅ์ ์ฌ๋ก
1
2
3
Heap ์ฆ๊ฐ
โ Full GC ์ฆ๊ฐ
โ OOM ๋ฐ์
ํนํ:
Tomcat
Spring MVC
Async ์ฒ๋ฆฌ
ํ๊ฒฝ์์ ํํ๋ค.
์ค๋ฌด์์ ์ค์ํ ๋์์ฑ ๋ฌธ์
๋ํ ์ฌ๋ก:
์ฃผ๋ฌธ ์ค๋ณต ์์ฑ
์ฌ๊ณ ์์
์ค๋ณต ๊ฒฐ์
์บ์ ์ค์ผ
์ค์ ์์
1
2
3
4
์ฌ๊ณ 1๊ฐ
Thread1 ๊ตฌ๋งค
Thread2 ๊ตฌ๋งค
๋ ๋ค ์ฑ๊ณต ๊ฐ๋ฅ.
์ ์ด๋ ค์ด๊ฐ?
๋์์ฑ ๋ฌธ์ ๋:
โ๊ฐ๋๋ง ๋ฐ์โ
ํ๋ค.
์ฆ:
์ฌํ ์ด๋ ค์
ํ ์คํธ ์ด๋ ค์
์ด์์์๋ง ํฐ์ง
๋งค์ฐ ์ํํ๋ค.
์ฑ๋ฅ ๊ด์
๋๊ธฐํ๋ ํญ์ Trade-off ์กด์ฌ.
lock ๋ง์ด ์ฌ์ฉ
์ฅ์ :
- ์์ ์ฑ ์ฆ๊ฐ
๋จ์ :
- throughput ๊ฐ์
lock ์ค์ด๋ฉด
์ฅ์ :
- ์ฑ๋ฅ ํฅ์
๋จ์ :
- race condition ์ํ
์์ฃผ ๋ฐ์ํ๋ ์ค์
1. volatile์ด๋ฉด ์์ ํ๋ค๊ณ ์ฐฉ๊ฐ
Atomicity ๋ณด์ฅ ์ ํจ.
2. HashMap ๋ฉํฐ Thread ์ฌ์ฉ
์ค๋ฌด ์ฅ์ ํํจ.
3. ThreadLocal remove ๋๋ฝ
๋ฉ๋ชจ๋ฆฌ leak ๋ฐ์.
4. synchronized ๋จ์ฉ
์ฑ๋ฅ ๋ณ๋ชฉ ๊ฐ๋ฅ.
๋ฉด์ ๊ผฌ๋ฆฌ ์ง๋ฌธ
Q1. synchronized๋ ๋ฌด์์ ๋ณด์ฅํ๋์?
ํต์ฌ:
mutual exclusion
visibility
Q2. volatile์ ์ ํ์ํ๊ฐ์?
ํต์ฌ:
- CPU cache visibility ๋ฌธ์ ํด๊ฒฐ
Q3. volatile์ด atomicity๋ฅผ ๋ณด์ฅํ๋์?
์ ๋ต:
- ์๋๋ค
Q4. CAS๋ ๋ฌด์์ธ๊ฐ์?
ํต์ฌ:
- lock-free atomic operation
Q5. ThreadLocal leak์ ์ ๋ฐ์ํ๋์?
ํต์ฌ:
Thread Pool ์ฌ์ฌ์ฉ
remove ๋๋ฝ
์ข์ ๋ต๋ณ ์์
Java Thread๋ Heap ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ Race Condition ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
synchronized๋ Monitor Lock์ ํตํด mutual exclusion๊ณผ memory visibility๋ฅผ ๋ณด์ฅํฉ๋๋ค.
volatile์ ์ต์ ๊ฐ visibility๋ง ๋ณด์ฅํ๋ฉฐ atomicity๋ ๋ณด์ฅํ์ง ์์ต๋๋ค.
Atomic ํด๋์ค๋ CAS ๊ธฐ๋ฐ lock-free ๋ฐฉ์์ผ๋ก ๋์ํ๋ฉฐ ThreadLocal์ Thread Pool ํ๊ฒฝ์์ remove ๋๋ฝ ์ ๋ฉ๋ชจ๋ฆฌ leak์ ์ ๋ฐํ ์ ์์ต๋๋ค.
๊ด๋ จ CS ๊ฐ๋ ์ฐ๊ฒฐ
Race Condition
Memory Visibility
Mutual Exclusion
Compare-And-Swap
Lock-Free Algorithm
CPU Cache
Context Switching
ํ์ ์์ ํนํ ์ค์ํ ํฌ์ธํธ
1. ๋์์ฑ ๋ฌธ์ ๋ ์ด์์์ ํฐ์ง๋ค
์ฌํ ์ด๋ ค์.
2. volatile ์คํด ๋งค์ฐ ๋ง๋ค
visibility๋ง ๋ณด์ฅ.
3. ThreadLocal leak ๋งค์ฐ ํํ๋ค
์ค๋ฌด ๋จ๊ณจ ์ฅ์ .
4. synchronized vs CAS Trade-off ์ค์
์ฑ๋ฅ๊ณผ ์์ ์ฑ ๊ท ํ ํ์.
ํต์ฌ ์์ฝ
Thread๋ Heap ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๋ค
Race Condition์ ์คํ ์์ ๋ฌธ์ ๋ค
synchronized๋ lock ๊ธฐ๋ฐ ๋๊ธฐํ๋ค
volatile์ visibility๋ง ๋ณด์ฅํ๋ค
Atomic์ CAS ๊ธฐ๋ฐ lock-free ๋ฐฉ์์ด๋ค
ThreadLocal์ Thread Pool ํ๊ฒฝ์์ leak ์ํ์ด ์๋ค
๋์์ฑ ๋ฌธ์ ๋ ์ค์ ์ด์ ์ฅ์ ์ ๋งค์ฐ ๋ฐ์ ํ๋ค