How to Use Locks in Multi-Threaded Java Program?

02 Feb, 2021
A lock may be a more flexible and complicated thread synchronization mechanism than the standard synchronized block. A lock may be a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: just one thread at a time can acquire the lock and everyone accesses to the shared resource requires that the lock be acquired first. However, some locks may allow concurrent access to a shared resource, like the read lock of a ReadWriteLock.
// Example of lock interface
Lock lock = new ReentrantLock();
lock.lock();
 
// critical section 
lock.unlock();
Methods in the lock interface
There are certain methods in a lock interface. We are gonna look at those along with their modifiers:
Implementation of locks
Let’s see how can we implement some locks in Java:
1.readWriteLock()
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

readWriteLock.readLock().lock();

    // ....
    
    
                ......//

readWriteLock.readLock().unlock();


readWriteLock.writeLock().lock();

    // only one writer can enter this section,
    // and only if no threads are currently reading.

readWriteLock.writeLock().unlock();
Below is the implementation of readWriteLock() method:
Java
// Implementation of ReadWriteLock in Javaimport java.io.*;import java.util.ArrayList;import java.util.List;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;class GFG<O> {      private final ReadWriteLock readWriteLock        = new ReentrantReadWriteLock();    private final Lock writeLock        = readWriteLock.writeLock();    private final Lock readLock = readWriteLock.readLock();    private final List<O> list = new ArrayList<>();      // setElement function sets    // i.e., write the element to the thread    public void setElement(O o)    {        // acquire the thread for writing        writeLock.lock();        try {            list.add(o);            System.out.println(                "Element by thread "                + Thread.currentThread().getName()                + " is added");        }        finally {            // To unlock the acquired write thread            writeLock.unlock();        }    }      // getElement function prints    // i.e., read the element from the thread    public O getElement(int i)    {        // acquire the thread for reading        readLock.lock();        try {            System.out.println(                "Elements by thread "                + Thread.currentThread().getName()                + " is printed");            return list.get(i);        }        finally {            // To unlock the acquired read thread            readLock.unlock();        }    }    public static void main(String[] args)    {        GFG<String> gfg = new GFG<>();          gfg.setElement("Hi");        gfg.setElement("Hey");        gfg.setElement("Hello");          System.out.println("Printing the last element : "                           + gfg.getElement(2));    }}
Element by thread main is added
Element by thread main is added
Element by thread main is added
Elements by thread main is printed
Printing the last element : Hello
2. reentrantLock()
public class lockImplement {
    //...
    ReentrantLock lock = new ReentrantLock();
    int counter = 0;

    public void testing() {
        lock.lock();
        try {
            // Critical section here
            count++;
        } finally {
            lock.unlock();
        }
    }
    //...
}
Below is the implementation of reentrantLock() method:
Java
// Java code to illustrate Reentrant Locksimport java.text.SimpleDateFormat;import java.util.Date;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.locks.ReentrantLock;  class worker implements Runnable {    String name;    ReentrantLock re;    public worker(ReentrantLock rl, String n)    {        re = rl;        name = n;    }    public void run()    {        boolean done = false;        while (!done) {            // Getting Outer Lock            boolean ans = re.tryLock();              // Returns True if lock is free            if (ans) {                try {                    Date d = new Date();                    SimpleDateFormat ft                        = new SimpleDateFormat("hh:mm:ss");                    System.out.println(                        "task name - " + name                        + " outer lock acquired at "                        + ft.format(d)                        + " Doing outer work");                    Thread.sleep(1500);                      // Getting Inner Lock                    re.lock();                    try {                        d = new Date();                        ft = new SimpleDateFormat(                            "hh:mm:ss");                        System.out.println(                            "task name - " + name                            + " inner lock acquired at "                            + ft.format(d)                            + " Doing inner work");                        System.out.println(                            "Lock Hold Count - "                            + re.getHoldCount());                        Thread.sleep(1500);                    }                    catch (InterruptedException e) {                        e.printStackTrace();                    }                    finally {                        // Inner lock release                        System.out.println(                            "task name - " + name                            + " releasing inner lock");                          re.unlock();                    }                    System.out.println("Lock Hold Count - "                                       + re.getHoldCount());                    System.out.println("task name - " + name                                       + " work done");                      done = true;                }                catch (InterruptedException e) {                    e.printStackTrace();                }                finally {                    // Outer lock release                    System.out.println(                        "task name - " + name                        + " releasing outer lock");                      re.unlock();                    System.out.println("Lock Hold Count - "                                       + re.getHoldCount());                }            }            else {                System.out.println("task name - " + name                                   + " waiting for lock");                try {                    Thread.sleep(1000);                }                catch (InterruptedException e) {                    e.printStackTrace();                }            }        }    }}  public class test {    static final int MAX_T = 2;    public static void main(String[] args)    {        ReentrantLock rel = new ReentrantLock();        ExecutorService pool            = Executors.newFixedThreadPool(MAX_T);        Runnable w1 = new worker(rel, "Job1");        Runnable w2 = new worker(rel, "Job2");        Runnable w3 = new worker(rel, "Job3");        Runnable w4 = new worker(rel, "Job4");        pool.execute(w1);        pool.execute(w2);        pool.execute(w3);        pool.execute(w4);        pool.shutdown();    }}
Output:
task name - Job2 waiting for lock
task name - Job1 outer lock acquired at 09:49:42 Doing outer work
task name - Job2 waiting for lock
task name - Job1 inner lock acquired at 09:49:44 Doing inner work
Lock Hold Count - 2
task name - Job2 waiting for lock
task name - Job2 waiting for lock
task name - Job1 releasing inner lock
Lock Hold Count - 1
task name - Job1 work done
task name - Job1 releasing outer lock
Lock Hold Count - 0
task name - Job3 outer lock acquired at 09:49:45 Doing outer work
task name - Job2 waiting for lock
task name - Job3 inner lock acquired at 09:49:47 Doing inner work
Lock Hold Count - 2
task name - Job2 waiting for lock
task name - Job2 waiting for lock
task name - Job3 releasing inner lock
Lock Hold Count - 1
task name - Job3 work done
task name - Job3 releasing outer lock
Lock Hold Count - 0
task name - Job4 outer lock acquired at 09:49:48 Doing outer work
task name - Job2 waiting for lock
task name - Job4 inner lock acquired at 09:49:50 Doing inner work
Lock Hold Count - 2
task name - Job2 waiting for lock
task name - Job2 waiting for lock
task name - Job4 releasing inner lock
Lock Hold Count - 1
task name - Job4 work done
task name - Job4 releasing outer lock
Lock Hold Count - 0
task name - Job2 outer lock acquired at 09:49:52 Doing outer work
task name - Job2 inner lock acquired at 09:49:53 Doing inner work
Lock Hold Count - 2
task name - Job2 releasing inner lock
Lock Hold Count - 1
task name - Job2 work done
task name - Job2 releasing outer lock
Lock Hold Count - 0
Note: The program might not work on an online IDE because of sleep call.
Java-Multithreading
Picked
Technical Scripter 2020
Java
Java Programs
Technical Scripter
Java
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.