MTI TEK
  • Home
  • LLMs
  • Docker
  • Kubernetes
  • Java
Java | locks: ReentrantLock
  1. ReentrantLock
  2. Problem
  3. Using ReentrantLock to solve this problem

  1. ReentrantLock
    ReentrantLock is a synchronization primitive in Java's java.util.concurrent.locks package that provides explicit locking mechanisms. Unlike synchronized blocks, ReentrantLock offers more flexibility with features like tryLock(), timed locking, and interruptible lock acquisition. The "reentrant" aspect means the same thread can acquire the lock multiple times without deadlocking itself, making it safe for recursive method calls.
  2. Problem
    First we will look at this example:
    private Integer id = Integer.valueOf(0);
    
    public void updateId(final Integer localId) {
        this.id = localId;
        System.out.println("localId: " + localId + " / id:" + this.id);
    }
    The problem with this example is if multiple threads call this method, the value of the instance variable "id" that we print at the end of the method can be different from the value of the parameter "localId".

    If 5 concurrent threads call this method, the output could be something like the following:
    localId: 2 / id:3
    localId: 4 / id:3
    localId: 1 / id:3
    localId: 0 / id:3
    localId: 3 / id:3
  3. Using ReentrantLock to solve this problem
    Here's the minimal dependencies needed in order for the following example to work ("pom.xml" file):
    <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.17.0</version>
    </dependency>
    Note: The Apache Commons Lang3 dependency is included for the BasicThreadFactory class, which provides convenient thread naming and daemon thread configuration. While Java's built-in ReentrantLock works without additional dependencies, using a custom ThreadFactory allows better thread management and debugging.

    Example: Using ReentrantLock
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantLock;
    import java.util.stream.IntStream;
    
    import org.apache.commons.lang3.concurrent.BasicThreadFactory;
    
    public class MainClass {
        private final ReentrantLock lock = new ReentrantLock();
    
        private Integer id = Integer.valueOf(0);
    
        public void updateId(final Integer localId) {
            try {
                lock.lock();
    
                this.id = localId;
    
                // simulate a time-consuming code
                try {
                    Thread.sleep(500l);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                System.out.println("localId: " + localId + " / id:" + this.id);
            } finally {
                lock.unlock();
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            final String poolName = "_newFixedThreadPool";
    
            final BasicThreadFactory basicThreadFactory = new BasicThreadFactory.Builder().namingPattern(poolName).daemon(true).build();
    
            final ExecutorService executorService = Executors.newFixedThreadPool(5, basicThreadFactory);
    
            final MainClass mainClass = new MainClass();
    
            IntStream.iterate(0, i -> i + 1).limit(5).forEach(t -> executorService.execute(() -> {
                try {
                    // wait (random time) before calling the update method
                    Thread.sleep(new Random().nextInt(500) + 1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                mainClass.updateId(t);
            }));
    
            executorService.shutdown();
    
            executorService.awaitTermination(10000l, TimeUnit.MILLISECONDS);
        }
    }
    Output:
    localId: 2 / id:2
    localId: 0 / id:0
    localId: 1 / id:1
    localId: 4 / id:4
    localId: 3 / id:3
© 2025 mtitek
About