Lock framework vs Thread synchronization in Java

24 Sep, 2021
Thread synchronization mechanism can be achieved using Lock framework, which is present in java.util.concurrent package. Lock framework works like synchronized blocks except locks can be more sophisticated than Java’s synchronized blocks. Locks allow more flexible structuring of synchronized code. This new approach was introduced in Java 5 to tackle the below-mentioned problem of synchronization.
Let’s look at an Vector class, which has many synchronized methods. When there are 100 synchronized methods in a class, only one thread can be executed of these 100 methods at any given point in time. Only one thread is allowed to access only one method at any given point of time using a synchronized block. This is a very expensive operation. Locks avoid this by allowing the configuration of various locks for different purpose. One can have couple of methods synchronized under one lock and other methods under a different lock. This allows more concurrency and also increases overall performance.
Example: 
Lock lock = new ReentrantLock();
lock.lock();

// Critical section
lock.unlock();
A lock is acquired via the lock() method and released via the unlock() method. Invoking an unlock() without lock() will throw an exception. As already mentioned the Lock interface is present in java.util.concurrent.locks package and the ReentrantLock implements the Lock interface. 
Note: The number of lock() calls should always be equal to the number of unlock() calls.
In the below code, the user has created one resource named “TestResource” which has two methods and two different locks for each respectively. There are two jobs named “DisplayJob” and “ReadJob”. The LockTest class creates 5 threads to accomplish ‘DisplayJob’ and 5 threads to accomplish ‘ReadJob’. All the 10 threads share single resource “TestResource”.
Java
import java.util.Date;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock; // Test class to test the lock example// 5 threads are created with DisplayJob// and 5 thread are created with ReadJob.// Both these jobs use single TestResource named "test".public class LockTest{    public static void main(String[] args)    {        TestResource test = new TestResource();        Thread thread[] = new Thread[10];          for (int i = 0; i < 5; i++)          {             thread[i] = new Thread(new DisplayJob(test),             "Thread " + i);          }          for (int i = 5; i < 10; i++)          {             thread[i] = new Thread(new ReadJob(test),             "Thread " + i);          }          for (int i = 0; i < 10; i++)          {             thread[i].start();          }    } }// DisplayJob class implementing Runnable interface.// This uses TestResource object passed in the constructor.// run method invokes displayRecord method on TestResource.class DisplayJob implements Runnable{         private TestResource test;    DisplayJob(TestResource tr)    {        test = tr;    }    @Override    public void run()    {        System.out.println("display job");        test.displayRecord(new Object());    }}// ReadJob class implementing Runnable interface.// which uses TestResource object passed in the constructor.// run method invokes readRecord method on TestResource.class ReadJob implements Runnable{         private TestResource test;         ReadJob(TestResource tr)    {        test = tr;    }    @Override    public void run()    {        System.out.println("read job");        test.readRecord(new Object());    }}// Class which has two locks and two methods. class TestResource{         // displayQueueLock is created to make    // displayQueueLock thread safe.    // When T1 acquires lock on testresource(o1)    // object displayRecord method    // T2 has to wait for lock to be released    // by T1 on testresource(o1) object    // displayRecord method.  But T3, can execute     // readRecord method with out waiting for lock    // to be released by t1 as    // readRecord method uses readQueueLock not    // displayQueueLock.    private final Lock    displayQueueLock = new ReentrantLock();    private final Lock    readQueueLock = new ReentrantLock();     // displayRecord uses displayQueueLock to    // achieve thread safety.    public void displayRecord(Object document)    {        final Lock displayLock = this.displayQueueLock;        displayLock.lock();        try          {             Long duration =                         (long) (Math.random() * 10000);             System.out.println(Thread.currentThread().             getName() + ": TestResource: display a Job"+             " during " + (duration / 1000) + " seconds ::"+             " Time - " + new Date());             Thread.sleep(duration);          }          catch (InterruptedException e)          {             e.printStackTrace();          }          finally          {             System.out.printf("%s: The document has been"+             " dispalyed\n", Thread.currentThread().getName());             displayLock.unlock();          }    }     // readRecord uses readQueueLock to achieve thread safety.       public void readRecord(Object document)    {        final Lock readQueueLock = this.readQueueLock;        readQueueLock.lock();        try          {             Long duration =                       (long) (Math.random() * 10000);             System.out.println             (Thread.currentThread().getName()             + ": TestResource: reading a Job during " +             (duration / 1000) + " seconds :: Time - " +             new Date());             Thread.sleep(duration);          }          catch (InterruptedException e)          {             e.printStackTrace();          }          finally          {             System.out.printf("%s: The document has"+             " been read\n", Thread.currentThread().getName());             readQueueLock.unlock();          }    }}
Output: 
display job display job display job display job display job read job read job read job read job read job Thread 5: TestResource: reading a Job during 4 seconds :: Time – Wed Feb 27 15:49:53 UTC 2019 Thread 0: TestResource: display a Job during 6 seconds :: Time – Wed Feb 27 15:49:53 UTC 2019 Thread 5: The document has been read Thread 6: TestResource: reading a Job during 4 seconds :: Time – Wed Feb 27 15:49:58 UTC 2019  
In the above example, DisplayJob not required to wait for ReadJob threads to complete the task as ReadJob and Display job uses two different locks. This can not be possible with “synchronized”.
Differences are as follows:  
Lock.lock(); myMethod();Lock.unlock();
unlock() cant be executed in this code if any exception being thrown from myMethod().
 
khushboogoyal499
Java-Multithreading
Difference Between
Java
Java
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Difference between Synchronous and Asynchronous Transmission
Difference Between Method Overloading and Method Overriding in Java
Difference Between Go-Back-N and Selective Repeat Protocol
Time complexities of different data structures
Difference between Compile-time and Run-time Polymorphism in Java
Arrays in Java
Object Oriented Programming (OOPs) Concept in Java
Arrays.sort() in Java with examples
Reverse a string in Java
Split() String method in Java with examples