๐ŸŽ‰ Special Offer !    Code: GET300OFF    Flat โ‚น300 OFF on every Java Course
Grab Deal ๐Ÿš€

Synchronized Block  


Introduction
  • A synchronized block in Java is used to perform synchronization on a specific portion of code inside a method, rather than synchronizing the entire method.
  • When a method has many lines of code but only a few lines need synchronization, we use a synchronized(objectReference) block to lock only those lines.
  • Synchronizing only the critical section improves performance because the remaining code executes without a lock.
  • Points to Remember:
    • Object Locking: A synchronized block locks only the object specified in the block.
    • Smaller Scope: The scope of a synchronized block is smaller than a synchronized method.
    • Better Performance: Since only a small part of code is locked, synchronized blocks are generally faster than synchronized methods.
    • Access Control: It allows only one thread at a time to execute the code inside the block for the locked object.
    • System Performance: Overuse of synchronization can still slow down the application, so use it only where needed.
  • Syntax:-
    // Synchronizing on current object
    synchronized (this)
    {
        // Critical section code
    }
    // Synchronizing on a specific object
    synchronized (objectReference)
    {
        // Critical section code
    }
    Note:
    • A synchronized block must always be inside a method or a constructor, because it locks a specific object during the execution of that portion of code.
  • Program:
    class BookMovieSeat
    {
        int total_seats = 10;
    
        void bookSeat(int seats, String name)
        {
            // Some lines of code which are not synchronized (can run concurrently)
    
            synchronized (this)  // synchronized block
            {
                if (total_seats >= seats)
                {
                    System.out.println(name + " booked " + seats + " seats successfully");
                    total_seats = total_seats - seats;
                    System.out.println("Total seats left : " + total_seats);
                }
                else
                {
                    System.err.println(name + " sorry...!! seats not left");
                    System.err.println("Total seats left : " + total_seats);
                }
            }
    
            // Some lines of code which are not synchronized (can run concurrently)
        }
    }
    
    class MyThread extends Thread
    {
        BookMovieSeat bts;
        int seats;
    
        public MyThread(BookMovieSeat bts, int seats)
        {
            this.bts = bts;
            this.seats = seats;
        }
    
        public void run()
        {
            bts.bookSeat(seats, Thread.currentThread().getName());
        }
    }
    
    public class MovieBookingApp
    {
        public static void main(String[] args)
        {
            BookMovieSeat bts = new BookMovieSeat();
    
            MyThread deepak = new MyThread(bts, 6);
            deepak.setName("Deepak");
            deepak.start();
    
            MyThread amit = new MyThread(bts, 5);
            amit.setName("Amit");
            amit.start();
        }
    }
  • Explanation:
    • Here we used a synchronized block inside the bookSeat() method instead of making the whole method synchronized.
    • This means only the critical section (code that modifies total_seats) is synchronized, not the entire method.
    • This approach improves performance since other non-critical code (if present) can execute without acquiring a lock.
    • Because of synchronization:
      • When Deepak thread starts executing the synchronized block, Amit must wait until the lock is released.
      • After Deepak finishes execution and releases the lock, Amit will enter the synchronized block and check the updated total_seats.
    • This ensures correct seat count, prevents race conditions, and avoids data inconsistency.