understanding deadlock livelock and starvation with code examples in java

Deadlock, livelock, and starvation are all problems that can occur in multithreaded programs that involve shared resources. Here's an overview of each problem, along with code examples in Java that illustrate each one.

  1. Deadlock

Deadlock occurs when two or more threads are blocked, waiting for each other to release resources that they need. In other words, each thread is holding a resource that the other thread needs, and neither thread can make progress.

Here's an example of a simple deadlock situation in Java:

public class DeadlockExample {
    private static Object lock1 = new Object();
    private static Object lock2 = new Object();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (lock1) {
                System.out.println("Thread 1 acquired lock 1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {}
                synchronized (lock2) {
                    System.out.println("Thread 1 acquired lock 2");
                }
            }
        });

        Thread t2 = new Thread(() -> {
            synchronized (lock2) {
                System.out.println("Thread 2 acquired lock 2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {}
                synchronized (lock1) {
                    System.out.println("Thread 2 acquired lock 1");
                }
            }
        });

        t1.start();
        t2.start();
    }
}
‮uoS‬rce:www.theitroad.com

In this example, two threads are trying to acquire two different locks in a different order, resulting in a deadlock situation. Thread 1 acquires lock 1 and then waits for lock 2, while Thread 2 acquires lock 2 and then waits for lock 1. Since neither thread can proceed, the program will hang indefinitely.

  1. Livelock

Livelock occurs when two or more threads are actively trying to resolve a deadlock situation, but end up continuously blocking each other without making progress. In other words, the threads are not waiting passively like in a deadlock, but actively attempting to resolve the problem, resulting in a loop of blocking and unblocking each other.

Here's an example of a simple livelock situation in Java:

public class LivelockExample {
    private static boolean sharedResource = false;

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            while (!sharedResource) {
                System.out.println("Thread 1 is waiting for the shared resource");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {}
            }
            System.out.println("Thread 1 acquired the shared resource");
            sharedResource = false;
        });

        Thread t2 = new Thread(() -> {
            while (sharedResource) {
                System.out.println("Thread 2 is waiting for the shared resource");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {}
            }
            System.out.println("Thread 2 acquired the shared resource");
            sharedResource = true;
        });

        t1.start();
        t2.start();
    }
}

In this example, two threads are trying to access a shared resource that can only be held by one thread at a time. However, rather than simply blocking if the resource is already held, the threads continuously check if the resource is available, resulting in a loop of blocking and unblocking each other. Since neither thread can make progress, the program will hang indefinitely.

  1. Starvation

Starvation occurs when one or more threads are prevented from accessing a shared resource for an extended period of time, due to other threads holding the resource for long periods of time. In other words