What is a real time example of synchronization in Java?

Octavia 79 Published: 09/24/2024

What is a real time example of synchronization in Java?

One of the most common and straightforward examples of synchronization in Java is the Producer-Consumer problem. Imagine you have a shared resource, like a plate of food at a party, where multiple people can take food from it (produce) and multiple people can put food on it (consume). Without proper control, this could lead to chaos: someone might try to take an empty plate or put more food than the plate can hold.

In Java, we use threads to simulate these producers and consumers. Each thread represents a person trying to access the shared resource. The problem arises when multiple threads simultaneously try to read from (consume) or write to (produce) this shared resource.

Here's how you could solve this issue using synchronization in Java:

public class ProducerConsumerExample {

private static final int LIMIT = 10; // Maximum capacity of the plate

private static final int SLEEP_MILLIS = 1000; // Time delay between actions

private static volatile boolean producerShouldRun = true;

private static final Object lock = new Object();

private static volatile int totalFoodOnPlate = 0;

public static void main(String[] args) {

Thread producerThread = new Thread(new Producer());

Thread consumerThread = new Thread(new Consumer());

// Start the threads

producerThread.start();

consumerThread.start();

// Wait for both threads to finish

producerShouldRun = false;

producerThread.join();

consumerThread.join();

}

static class Producer implements Runnable {

@Override

public void run() {

try {

while (producerShouldRun) {

int amountOfFoodToProduce = new Random().nextInt(LIMIT - totalFoodOnPlate) + 1;

synchronized (lock) {

// Check if there's space on the plate before producing

if (totalFoodOnPlate + amountOfFoodToProduce > LIMIT) {

System.out.println("Plate is full. Waiting...");

lock.wait();

}

totalFoodOnPlate += amountOfFoodToProduce;

}

Thread.sleep(SLEEP_MILLIS);

}

} catch (InterruptedException e) {

// Handle the interruption

}

}

}

static class Consumer implements Runnable {

@Override

public void run() {

try {

while (true) {

synchronized (lock) {

// Check if there's food on the plate before consuming

if (totalFoodOnPlate == 0) {

System.out.println("No food left. Waiting...");

lock.wait();

}

int amountOfFoodToConsume = new Random().nextInt(totalFoodOnPlate) + 1;

totalFoodOnPlate -= amountOfFoodToConsume;

}

Thread.sleep(SLEEP_MILLIS);

}

} catch (InterruptedException e) {

// Handle the interruption

}

}

}

}

In this example, totalFoodOnPlate represents the shared resource. The producer thread tries to add more food than the plate can hold if it's already full, while the consumer thread tries to consume food from an empty plate. Both threads are synchronized on the same lock object (lock) before accessing totalFoodOnPlate.

When a thread tries to access totalFoodOnPlate and finds it's in an inconsistent state (e.g., trying to consume when there's no food left or trying to produce when the plate is already full), the thread waits until the other thread has resolved the inconsistency. This ensures that the shared resource is always in a consistent state.

This example illustrates synchronization by controlling access to shared resources, preventing data corruption and ensuring thread safety.

What is the difference between join and synchronization in Java?

In Java, both join and synchronization are related to managing the execution of threads, but they serve distinct purposes.

Join: The join method is used to wait for a thread's completion before continuing with the current thread's execution. When a thread calls join() on another thread, it temporarily blocks its own execution until the joined thread terminates or exits. This allows the joining thread to ensure that any shared resources or data modified by the joined thread are updated before proceeding.

Imagine you're running a marathon and your friend is ahead of you. You want to make sure they've crossed the finish line before you do. That's roughly what join does – it waits for the other thread (your friend) to complete its task (crossing the finish line) before proceeding with your own task.

Here are some key points about join:

It's a blocking call, meaning the calling thread is paused until the joined thread completes. If the joined thread exits abruptly (e.g., due to an exception), the joiner will also be notified of this termination. You can specify a timeout when calling join, which allows you to set a maximum waiting time before raising an exception.

Synchronization: Synchronization refers to the mechanisms used to coordinate access to shared resources and data by multiple threads. In Java, synchronization is achieved using locks (e.g., synchronized methods or statements), monitors (e.g., Object.wait() and notify()), and atomic variables (e.g., AtomicInteger).

Think of it like a busy highway: you need rules to ensure safe merging and passing between cars. In Java, synchronization provides the "rules" for threads to share resources and data without conflicts.

Here are some key points about synchronization:

Synchronization ensures that only one thread can access a shared resource at a time, preventing concurrent modifications or interference. Locks (e.g., synchronized blocks) protect critical sections of code by ensuring exclusive access. Monitors allow threads to wait and be notified when a specific condition is met.

In summary:

Join waits for another thread's completion before proceeding with the current thread's execution. Synchronization coordinates access to shared resources and data among multiple threads, ensuring safe sharing and preventing concurrent modifications or interference.

While both concepts are essential in Java multithreading programming, they serve distinct purposes. You might use join when you need to ensure that a specific thread has completed its task before proceeding with your own, whereas synchronization is crucial for managing shared resources and data among multiple threads.