π§© κ΅μ°© μν(Deadlock) λ°μ 쑰건과 μλ°μμμ ν΄κ²° λ°©λ²
κ΅μ°© μνλ λ κ° μ΄μμ μμ μ΄ μλ‘ μλλ°©μ μμ μ΄ λλκΈ°λ§μ κΈ°λ€λ¦¬λ μν©μ λ§ν©λλ€.
κ²°κ³Όμ μΌλ‘ μ΄λ€ μμ λ μλ£λμ§ λͺ»νκ³ λ¬΄ν λκΈ° μνμ λΉ μ§κ² λ©λλ€.
π¦ μμ: κ΅μ°© μνλ?
- A μ€λ λκ°
resource1
μ κ°μ§κ³resource2
λ₯Ό κΈ°λ€λ¦Ό - B μ€λ λκ°
resource2
λ₯Ό κ°μ§κ³resource1
μ κΈ°λ€λ¦Ό
// Thread A
synchronized (resource1) {
synchronized (resource2) {
// μμ
}
}
// Thread B
synchronized (resource2) {
synchronized (resource1) {
// μμ
}
}
π₯ μλ‘ lock
μ μ‘μ μνμμ μλλ°©μ΄ κ°μ§ lock
μ κΈ°λ€λ¦¬λ, λ μ€λ λλ μμν μλ‘λ₯Ό κΈ°λ€λ¦¬κ² λ©λλ€.
π κ΅μ°© μν λ°μ 쑰건 (4κ°μ§)
쑰건 μ΄λ¦ | μ€λͺ |
---|---|
μνΈ λ°°μ (Mutual Exclusion) | μμμ νλμ νλ‘μΈμ€λ§ μ¬μ©ν μ μμ |
μ μ λκΈ° (Hold and Wait) | μμμ κ°μ§ μνμμ λ€λ₯Έ μμμ κΈ°λ€λ¦Ό |
λΉμ μ (Non-Preemption) | λ€λ₯Έ νλ‘μΈμ€κ° μμμ κ°μ λ‘ λΉΌμμ μ μμ |
μν λκΈ° (Circular Wait) | νλ‘μΈμ€ κ° μμ μμ²μ΄ μνμΌλ‘ μ°κ²°λ¨ |
π§ μ΄ 4κ°μ§κ° λͺ¨λ λ§μ‘±λ λ κ΅μ°© μνκ° λ°μν μ μμ΅λλ€.
π§― μλ°μμ κ΅μ°© μν ν΄κ²° λ°©λ²
β
1. synchronized
μ€μ²© μ κ±°λ‘ μ μ λκΈ° λ°©μ§
// μνν ꡬ쑰
synchronized (resource1) {
synchronized (resource2) {
// μ μ¬μ Deadlock
}
}
- κ°μ λ°©λ²: μμμ μμ°¨μ μΌλ‘ μμ²νκ±°λ, μ€μ²©λ
synchronized
λΈλ‘μ νΌνλ€.
β
2. ReentrantLock
+ tryLock()
μ¬μ©
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();
if (lock1.tryLock(1, TimeUnit.SECONDS)) {
try {
if (lock2.tryLock(1, TimeUnit.SECONDS)) {
try {
// μμ
μν
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
tryLock()
μ μ¬μ©νλ©΄ μΌμ μκ° λ΄ λ½μ νλνμ§ λͺ»νλ©΄ νμΆ κ°λ₯νλ―λ‘ Deadlockμ λ°©μ§ν μ μμ
β
3. lockInterruptibly()
λ‘ μΈν°λ½νΈ μ²λ¦¬
lock1.lockInterruptibly(); // μΈν°λ½νΈ κ°λ₯νκ² λκΈ°
- μΈλΆμμ
Thread.interrupt()
νΈμΆ μ λ½ λκΈ° μ€μΈ μ€λ λλ₯Ό κΉ¨μμ ν볡 κ°λ₯ν©λλ€.
π― μ 리
λ°©λ² | μ€λͺ |
---|---|
π μμ 보μ₯ | μμ νλ μμλ₯Ό ν΅μΌνμ¬ Circular Wait μ κ±° |
β μ€μ²© νΌνκΈ° | μ€μ²©λ synchronized μ¬μ© μ΅μν |
β° tryLock μ¬μ© | μΌμ μκ° λ΄ λ½ νλ μ€ν¨ μ ννΌ |
π¨ lockInterruptibly | μΈλΆμμ μ€λ λ μΈν°λ½νΈλ‘ μ μ΄ |
λκΈλ¨κΈ°κΈ°