HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
남득윤 학습 저장소
/
🧵
멀티쓰레드, 동시성 프로그래밍
/
🧵
Java Concurrency and Multithreding
/
Deadlock in Java

Deadlock in Java

 

Deadlock defintion

💡
Deadlock is a situation that can occur when two or more threads are blocked indefinitely trying to obtain access to a resource locked by the other threads in the deadlock. Thus, the deadlocked threads are blocked, waiting for each other to release a resource which neither of them can release because they are blocked waiting for the other thread to release its resource first.
💡
Such resources can be Java Locks, Java synchronized blocks (Java monitor objects), files, database tables and / or records etc.
notion image

Deadlock code example using two Lock instances in Java

public class DeadLockExample { public static void main(String[] args) { Lock lock1 = new ReentrantLock(); Lock lock2 = new ReentrantLock(); Thread thread1 = new Thread(new Runnable1(lock1, lock2)); Thread thread2 = new Thread(new Runnable2(lock1, lock2)); thread1.start(); thread2.start(); } }
public class Runnable1 implements Runnable{ private Lock lock1 = null; private Lock lock2 = null; public Runnable1(Lock lock1, Lock lock2) { this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName+ " attempt to lock Lock1"); lock1.lock(); System.out.println(threadName+ " lock Lock1"); try { sleep(3000); } catch (InterruptedException e) { } System.out.println(threadName+ " attempt to lock Lock2"); lock2.lock(); System.out.println(threadName+ " lock Lock2"); //do the work - 두 lock 모두 lock함 //unlock System.out.println(threadName+ " unlock Lock1"); lock1.unlock(); System.out.println(threadName+ " unlock Lock2"); lock2.unlock(); } }
public class Runnable2 implements Runnable{ private Lock lock1 = null; private Lock lock2 = null; public Runnable2(Lock lock1, Lock lock2) { this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName+ " attempt to lock Lock2"); lock2.lock(); System.out.println(threadName+ " lock Lock2"); try { sleep(3000); } catch (InterruptedException e) { } System.out.println(threadName+ " attempt to lock Lock1"); lock1.lock(); System.out.println(threadName+ " lock Lock1"); //unlock System.out.println(threadName+ " unlock Lock1"); lock1.unlock(); System.out.println(threadName+ " unlock Lock2"); lock2.unlock(); } }
실행결과 - unlock 안함 (그림의 상황)
Thread-1 attempt to lock Lock2 Thread-0 attempt to lock Lock1 Thread-0 lock Lock1 Thread-1 lock Lock2 Thread-0 attempt to lock Lock2 Thread-1 attempt to lock Lock1
 

Deadlock code example using two synchronized blocks in Java

public class DeadLockSyncExample { public static void main(String[] args) { Lock lock1 = new ReentrantLock(); Lock lock2 = new ReentrantLock(); Thread thread1 = new Thread(new RunnableSync1(lock1, lock2)); Thread thread2 = new Thread(new RunnableSync2(lock1, lock2)); thread1.start(); thread2.start(); } }
public class RunnableSync1 implements Runnable{ private Object lock1 = null; private Object lock2 = null; public RunnableSync1(Lock lock1, Lock lock2) { this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName+ " attempt to lock Lock1"); synchronized (lock1) { System.out.println(threadName + " lock Lock1"); try { sleep(3000); } catch (InterruptedException e) { } System.out.println(threadName + " attempt to lock Lock2"); synchronized (lock2){ System.out.println(threadName + " lock Lock2"); //do the work - 두 lock 모두 lock함 System.out.println(threadName + " unlock Lock2"); } System.out.println(threadName + " unlock Lock1"); } } }
public class RunnableSync2 implements Runnable{ private Object lock1 = null; private Object lock2 = null; public RunnableSync2(Lock lock1, Lock lock2) { this.lock1 = lock1; this.lock2 = lock2; } @Override public void run() { String threadName = Thread.currentThread().getName(); System.out.println(threadName+ " attempt to lock Lock2"); synchronized (lock2) { System.out.println(threadName + " lock Lock2"); try { sleep(3000); } catch (InterruptedException e) { } System.out.println(threadName + " attempt to lock Lock1"); synchronized (lock1){ System.out.println(threadName + " lock Lock1"); //do the work - 두 lock 모두 lock함 System.out.println(threadName + " unlock Lock1"); } System.out.println(threadName + " unlock Lock2"); } } }
  • 여기도 데드락 걸림

Deadlock can occur with any mutually exclusive access / lockable resource

  • 데드락은 여러 쓰레드가 접근해서 락을 거는 어떠한 리소스에도 터질 수 있다.
 

Deadlock fix via lock ordering

  • lock 접근 순서를 둘다 lock1, lock2로 함 → 데드락 안걸림
 

More complex deadlock scenario

notion image
e.g. DB 테이블 락, 파일 락 등등

A deadlock will block all threads trying to lock a resource involved in the deadlock

notion image
  • 데드락에 접근하는 새로운 쓰레드들은 block된다.
 

The four conditions required for a deadlock to occur

  1. Mutual Exclusion
  1. No Preemption
  1. Hold and Wait
  1. Circular Wait

Other problems similar to deadlock

  • Livelock
  • Nested Moniter Lockout
  • Reentrance lockout
  • Starvation