Showing posts with label Java Synchronization. Show all posts
Showing posts with label Java Synchronization. Show all posts

Wednesday, 11 September 2013

Monitor or synchronization Design Pattern

🚀 Master Concurrency & Multithreading in Java!

Subscribe to Ram N Java for clean, visual, and beginner-friendly programming tutorials!

🔔 Subscribe Now

What is the Monitor (Synchronization) Design Pattern?

The Monitor Pattern (also widely referred to as the Synchronization Design Pattern) is a fundamental concurrency pattern used to coordinate concurrent access to shared resources.

Core Definition: In concurrent programming, a monitor is an object or module intended to be used safely by more than one thread. Its defining characteristic is that its methods are executed with mutual exclusion. That is, at each point in time, at most one thread may be executing any of its methods.

The Problem: Shared Bank Account Race Condition

Imagine a joint bank account shared by two individuals, John (Thread A) and Tina (Thread B). The account has an initial balance of ₹1,000.

Both John and Tina attempt to withdraw ₹1,000 at the exact same moment:

  1. Thread A (John): Invokes withdraw(1000). It checks the balance (₹1,000 ≥ ₹1,000) and passes validation. Before it updates the balance, the thread is preempted.
  2. Thread B (Tina): Enters withdraw(1000) simultaneously. Since the balance has not been deducted yet, it still sees ₹1,000. It passes the check, deducts ₹1,000, leaves the balance at ₹0, and dispenses the cash.
  3. Thread A Resumes: Now Thread A continues execution and subtracts ₹1,000 from the current balance (0 − 1,000 = −₹1,000), dispensing another ₹1,000!

As a result, ₹2,000 was withdrawn from an account that only contained ₹1,000, causing data inconsistency and balance corruption due to a classic race condition.

The Solution: Applying the Monitor Pattern

To prevent multiple threads from entering the critical section simultaneously, we apply the Monitor pattern by synchronizing the method. In Java, this is achieved cleanly using the synchronized keyword:

public class BankAccount {
    private int balance = 1000;

    // Synchronized method enforces Mutual Exclusion
    public synchronized boolean withdraw(int amount) {
        if (amount > 0 && balance >= amount) {
            balance -= amount;
            return true; // Withdrawal successful
        }
        return false; // Insufficient balance or invalid amount
    }

    public synchronized int getBalance() {
        return balance;
    }
}

How Mutual Exclusion Resolves the Conflict

  • When Thread A (John) calls withdraw(), it acquires the monitor lock on the BankAccount instance.
  • If Thread B (Tina) attempts to call withdraw() at the same time, it is blocked and forced to wait until Thread A finishes.
  • Thread A completes the deduction, leaving the balance at ₹0, and releases the monitor lock.
  • Thread B enters the method, checks the balance, finds insufficient funds (₹0 < ₹1,000), and is safely rejected.

Key Takeaways of the Monitor Pattern

  • Guarantees Mutual Exclusion: Only one thread executes critical method logic at any given time.
  • Prevents Race Conditions: Eliminates inconsistent state and corrupted business data in multithreaded environments.
  • Built-in Java Support: Every object in Java has an intrinsic monitor lock used by synchronized blocks/methods and wait() / notify() mechanisms.

Recommended Concurrency & Architecture Tutorials:


Click here to watch in Youtube : https://www.youtube.com/watch?v=VWeyrtcFEI0

Click the below Image to Enlarge
Monitor or synchronization Design Pattern
















See also:

  • All Design Patterns Links
  • Saturday, 3 August 2013

    Lock Design Pattern

    🚀 Master Concurrency & Multithreading in Java!

    Subscribe to Ram N Java for clean, visual, and beginner-friendly programming tutorials!

    🔔 Subscribe Now

    What is the Lock Design Pattern?

    In multithreaded systems, when multiple threads access and mutate shared resources concurrently, data corruption and race conditions can easily occur. The Lock Design Pattern provides an essential synchronization mechanism to safeguard shared data.

    Core Definition: The Lock Pattern ensures that one thread puts a lock on a shared resource, preventing other threads from accessing or modifying it until the operation is completed.

    The Problem: Shared Bank Account Without a Lock

    Consider a joint bank account shared between two people, John (Thread A) and Tina (Thread B). The account has a balance of ₹1,000. Both attempt to withdraw ₹1,000 at the same moment:

    1. Thread A (John): Calls the withdraw method for ₹1,000. It passes the precondition check (₹1,000 ≥ ₹1,000). Before deducting the balance, Thread A is suspended or sleeps.
    2. Thread B (Tina): Enters the method concurrently. Because the balance hasn't been updated yet, it still reads ₹1,000. It validates successfully, deducts ₹1,000, sets the balance to ₹0, and withdraws the money.
    3. Thread A Resumes: Now Thread A wakes up past the validation step and executes the deduction: 0 - 1000 = -1000, allowing John to withdraw ₹1,000 as well!

    Although only ₹1,000 was available in the account, a total of ₹2,000 was withdrawn, leaving the balance corrupted at −₹1,000.

    The Solution: Applying the Lock Pattern

    To resolve this race condition, we enforce mutual exclusion by placing a lock on the withdraw operation:

    public class BankAccount {
        private int balance = 1000;
    
        // Synchronized lock ensures mutual exclusion
        public synchronized void withdraw(int amount) {
            if (amount > 0 && balance >= amount) {
                System.out.println(Thread.currentThread().getName() + " is withdrawing: " + amount);
                balance -= amount;
                System.out.println("Remaining balance: " + balance);
            } else {
                System.out.println("Insufficient funds for: " + Thread.currentThread().getName());
            }
        }
    }

    How the Lock Mechanism Protects Data

    • When Thread A enters the method, it acquires the lock on the bank account resource.
    • If Thread B tries to enter, it is blocked because the lock is held. Thread B must wait until Thread A finishes.
    • Thread A completes the withdrawal, reduces the balance to ₹0, and releases the lock.
    • Thread B enters, re-evaluates the balance, finds insufficient funds (₹0 < ₹1,000), and is rejected safely without causing data inconsistency.

    Key Advantages of the Lock Pattern

    • Guarantees Thread Safety: Prevents multiple threads from simultaneously mutating shared variables.
    • Eliminates Race Conditions: Ensures atomic execution for critical sections of code.
    • Flexible Implementations: Can be achieved via intrinsic locks (synchronized blocks/methods) or explicit locks (java.util.concurrent.locks.ReentrantLock).

    Recommended Concurrency & Design Pattern Tutorials:


    Click here to watch in Youtube : https://www.youtube.com/watch?v=qTwq10Mj5DU

    Click the below Image to Enlarge
    Lock Design Pattern














    See also:

  • All Design Patterns Links
  • Tutorials