Immutability and Thread Safety in Java Part-3  

by ne on 2021-09-29 under Java

There are 4 sections of this Article:
Immutability and Thread Safety Part1- Covers Immutability
Immutability and Thread Safety Part2- Covers Thread Safety
[This one] Immutability and Thread Safety Part3- More on Thread Safety and Concurrency
Immutability and Thread Safety Part4 - Covers How the above 2 are related, and some further concepts

 

If you want to know the basics of a Thread , refer : Basics of Threads in Java

As we saw in  previous part, a multithreaded application can have many issues, when the shared resources are not properly handled.

Image showing multithreading expectation vs reality

Image Source : GOOGLE (https://qph.ec.quoracdn.net/main-qimg-1789e902515ae301430062bf5f514822-c)

 

So it is utmost important to make sure that you handle access to shared resources properly in case of multithreaded applications.

We saw, use of synchronized block, methods in previous article.

Now, let's discuss some more advanced ways of achieving thread safety.

Java has provided a huge number of handy and useful utility classes and a huge list of thread-safe data structures, which help in achieving thread-safety.The main package containing these utiltity classes and data structures is : java.util.concurrent

For instance, there is Lock interface, which contains handy methods like .lock(), .unlock(), .tryLock(), .tryLock(millis) etc.


package com.codinglords;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* Created by navsoni on 8/10/17.
*/
public class UseLock {
  Lock lock=new ReentrantLock();

  public void test(){

      synchronized (this){
          // critical and sensitive code
      }

      /**
       * the above synchronized block can be converted 
       * to below way of using Lock
       */

      lock.lock();
      // critical and sensitive code
      lock.unlock();

  }
}

The lock and unlock are straightforward methods, similar to entry-into-synchronized and leaving-from-synchronized method/block

But the tryLock and tryLock(long,timeunit), are much advanced and useful methods. If you want the thread to just try locking the object, if it is able to , it will lock it and return true, and we can continue with critical code, otherwise it will return false - in that case according to the business requirement, we can retry after some time.

And the tryLock(long,timeunit), will try to acquire lock till the provided time.


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by navsoni on 8/10/17.
 */
public class UseLock {
    Lock lock=new ReentrantLock();

    public void test(){

        try {
            if (lock.tryLock(1000, TimeUnit.MILLISECONDS)) {
                // sensitive code
            }
        }catch (InterruptedException ie){
            ie.printStackTrace();
        }finally {
            lock.unlock();
        }



    }
}

This gives the developer flexibility to not block the thread (like it was in synchronized).

 

Thanks

There are 4 sections of this Article:
Immutability and Thread Safety Part1- Covers Immutability
Immutability and Thread Safety Part2- Covers Thread Safety
[This one] Immutability and Thread Safety Part3- More on Thread Safety and Concurrency
​​​​​​​Immutability and Thread Safety Part4 - Covers How the above 2 are related, and some further concepts