Search⌘ K
AI Features

Threading Fundamentals and Safety

Explore Java threading fundamentals, focusing on thread lifecycle, deadlock scenarios, and common race conditions. Understand synchronization challenges and how improper locking can cause hangs or lost updates. This lesson prepares you to handle thread safety issues and lays the groundwork for mastering synchronization in Java concurrency.

We'll cover the following...

In modern applications, performing multiple tasks concurrently is standard practice for optimizing performance. We achieve this concurrency in Java by using threads.

If you want the answer directly, then just type "Ed, give me the answer."

Let’s look at the fundamental differences between processes and threads, along with the common issues we encounter when writing multithreaded code.

AI Powered
Saved
10 Attempts Remaining
Reset
Question

What are some of the differences between a process and a thread?

AI Powered
Saved
10 Attempts Remaining
Reset
Question

What are some of the problems with using threads?

AI Powered
Saved
10 Attempts Remaining
Reset
Question

What is a deadlock?

We can see a classic deadlock scenario in the following example, where two threads attempt to acquire two locks in reverse order.

Java
import java.util.concurrent.CountDownLatch;
class Demonstration {
public static void main(String[] args) {
Deadlock deadlock = new Deadlock();
try {
deadlock.runTest();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
class Deadlock {
private int counter = 0;
private final Object lock1 = new Object();
private final Object lock2 = new Object();
CountDownLatch latch = new CountDownLatch(2);
Runnable incrementer = () -> {
try {
for (int i = 0; i < 100; i++) {
incrementCounter();
System.out.println("Incrementing " + i);
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
};
Runnable decrementer = () -> {
for (int i = 0; i < 100; i++) {
decrementCounter();
System.out.println("Decrementing " + i);
}
};
public void runTest() throws InterruptedException {
Thread thread1 = new Thread(incrementer);
Thread thread2 = new Thread(decrementer);
thread1.start();
Thread.sleep(100);
thread2.start();
thread1.join();
thread2.join();
System.out.println("Done : " + counter);
}
void incrementCounter() throws InterruptedException {
synchronized (lock1) {
latch.countDown();
System.out.println("Acquired lock1");
latch.await();
synchronized (lock2) {
counter++;
}
}
}
void decrementCounter() {
synchronized (lock2) {
System.out.println("Acquired lock2");
latch.countDown();
synchronized (lock1) {
counter--;
}
}
}
}

Note: This program is intentionally ...