0% found this document useful (0 votes)
52 views7 pages

Deadlock in Java Multithreading and Strategies To Prevent It

Deadlock in Java occurs when threads are indefinitely waiting for resources held by each other, preventing any thread from proceeding. To prevent deadlocks, strategies include lock ordering, using tryLock(), implementing timeouts, and utilizing a single lock for resources. The effectiveness of these strategies varies, but they are essential for ensuring smooth multithreading operations.

Uploaded by

anvisuri05
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
52 views7 pages

Deadlock in Java Multithreading and Strategies To Prevent It

Deadlock in Java occurs when threads are indefinitely waiting for resources held by each other, preventing any thread from proceeding. To prevent deadlocks, strategies include lock ordering, using tryLock(), implementing timeouts, and utilizing a single lock for resources. The effectiveness of these strategies varies, but they are essential for ensuring smooth multithreading operations.

Uploaded by

anvisuri05
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Deadlock in Java Multithreading and Strategies to Prevent It

1. What is Deadlock?

A deadlock in Java occurs when two or more threads are waiting indefinitely for resources held by
each other, resulting in a situation where no thread can proceed. This happens when multiple
threads hold locks on shared resources and wait for additional locks that are held by other threads.

Example of a Deadlock Scenario

1. Thread A locks Resource 1 and waits for Resource 2.

2. Thread B locks Resource 2 and waits for Resource 1.

3. Since both threads are waiting on each other, neither can proceed, causing a deadlock.

2. Necessary Conditions for Deadlock

A deadlock can occur when all of the following four conditions hold simultaneously:

Condition Explanation

Mutual
A resource can be accessed by only one thread at a time.
Exclusion

Hold and Wait A thread holds at least one resource and waits for another.

No Preemption A resource cannot be forcibly taken away from a thread.

A set of threads form a circular chain, each waiting for a resource held by the next
Circular Wait
thread.

3. Example of Deadlock in Java

class Resource {

void methodA(Resource otherResource) {

synchronized (this) {

System.out.println(Thread.currentThread().getName() + " locked " + this);

try { Thread.sleep(100); } catch (InterruptedException e) {} // Simulate some work

synchronized (otherResource) {

System.out.println(Thread.currentThread().getName() + " locked " + otherResource);

}
public class DeadlockExample {

public static void main(String[] args) {

Resource resource1 = new Resource();

Resource resource2 = new Resource();

Thread thread1 = new Thread(() -> resource1.methodA(resource2), "Thread-1");

Thread thread2 = new Thread(() -> resource2.methodA(resource1), "Thread-2");

thread1.start();

thread2.start();

Output (Deadlock Occurs)

Thread-1 locked Resource@1a2b3c

Thread-2 locked Resource@4d5e6f

Threads are stuck waiting indefinitely.

4. How to Prevent Deadlock in Java?

1. Lock Ordering (Avoid Circular Wait Condition)

Always acquire locks in a consistent order. If all threads follow the same order while acquiring locks,
circular wait cannot occur.

Example (Corrected Code Using Lock Ordering)

class SafeResource {

void methodA(SafeResource otherResource) {

synchronized (this) {

System.out.println(Thread.currentThread().getName() + " locked " + this);

synchronized (otherResource) { // Always lock in the same order

System.out.println(Thread.currentThread().getName() + " locked " + otherResource);

}
}

Ensures that both threads always acquire locks in the same sequence, preventing circular wait.

2. Use tryLock() Instead of synchronized (Avoid Waiting Forever)

Use tryLock() from ReentrantLock instead of synchronized, so threads do not wait indefinitely.

Example Using tryLock()

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

class ResourceSafe {

private final Lock lock1 = new ReentrantLock();

private final Lock lock2 = new ReentrantLock();

void safeMethod() {

while (true) {

if (lock1.tryLock()) {

try {

if (lock2.tryLock()) {

try {

System.out.println(Thread.currentThread().getName() + " acquired both locks");

break;

} finally { lock2.unlock(); }

} finally { lock1.unlock(); }

// Retry after some time

try { Thread.sleep(50); } catch (InterruptedException ignored) {}

}
public class TryLockExample {

public static void main(String[] args) {

ResourceSafe resource = new ResourceSafe();

Thread t1 = new Thread(resource::safeMethod, "Thread-1");

Thread t2 = new Thread(resource::safeMethod, "Thread-2");

t1.start();

t2.start();

If a thread cannot acquire both locks, it releases the first lock and retries, avoiding deadlock.

3. Use a Timeout to Avoid Infinite Waiting

If a thread cannot acquire a lock within a set time, it backs off and retries later.

Example Using tryLock(timeout)

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

import java.util.concurrent.TimeUnit;

class TimeoutResource {

private final Lock lock1 = new ReentrantLock();

private final Lock lock2 = new ReentrantLock();

void safeMethod() {

try {

if (lock1.tryLock(100, TimeUnit.MILLISECONDS)) {

try {

if (lock2.tryLock(100, TimeUnit.MILLISECONDS)) {

try {

System.out.println(Thread.currentThread().getName() + " acquired both locks");


} finally { lock2.unlock(); }

} finally { lock1.unlock(); }

} else {

System.out.println(Thread.currentThread().getName() + " could not acquire locks,


retrying...");

} catch (InterruptedException ignored) {}

public class TimeoutExample {

public static void main(String[] args) {

TimeoutResource resource = new TimeoutResource();

Thread t1 = new Thread(resource::safeMethod, "Thread-1");

Thread t2 = new Thread(resource::safeMethod, "Thread-2");

t1.start();

t2.start();

If a thread cannot acquire both locks within 100ms, it retries later, preventing deadlock.

4. Use a Single Lock Instead of Multiple Locks

If possible, use one lock for all resources instead of multiple locks.

Example Using a Single Lock

import java.util.concurrent.locks.ReentrantLock;

class SingleLockResource {

private final ReentrantLock lock = new ReentrantLock();


void method() {

lock.lock();

try {

System.out.println(Thread.currentThread().getName() + " is executing.");

} finally {

lock.unlock();

public class SingleLockExample {

public static void main(String[] args) {

SingleLockResource resource = new SingleLockResource();

Thread t1 = new Thread(resource::method, "Thread-1");

Thread t2 = new Thread(resource::method, "Thread-2");

t1.start();

t2.start();

Since both threads use the same lock, deadlock cannot occur.

5. Summary of Deadlock Prevention Strategies

Strategy Description Effectiveness

Lock Ordering Always acquire locks in a fixed order Highly effective

Acquire locks only if available, avoid


Try-Lock (tryLock()) Prevents indefinite waiting
waiting

Timeout on Locks Use tryLock(timeout) to retry later Avoids long waits

Single Lock
Use one lock instead of multiple locks Prevents circular wait
Approach
Strategy Description Effectiveness

Do not hold one lock while waiting for Reduces risk but not always
Avoid Nested Locks
another possible

6. Conclusion

• Deadlock is a critical issue in Java multithreading that occurs when threads wait indefinitely
for each other.

• Prevention strategies like lock ordering, tryLock, timeouts, and single locks help avoid
deadlocks.

• Choosing the right strategy depends on the application requirements.

Would you like a real-world example, such as preventing deadlocks in a banking transaction
system?

You might also like