AtomicInteger for Lock Free Algorithms in Java - GeeksforGeeks

18 Sep, 2020
Lock-Free Algorithms is one of the mechanisms in which thread-safe access to shared data is possible without the use of Synchronization primitives like mutexes. Multi-threaded applications have shared resources that may be passed among different threads used in the application. 
This poses the threat of race conditions and data races among the threads. In order to handle this situation, various techniques are used. One of the most common ways is to use synchronization and locks(also called monitors) which ensures thread safety. However, If excessive synchronization is used, the application performance would be hugely impacted along with the application getting more and more complex. 
We need to write applications that are thread-safe but at the same time, they should give us high performance and the benefit of concurrent execution. So, in order to minimize the usage of synchronization and reduce the complexity of locks, Java has a whole set of classes in the java.util.the concurrent package which provides many advanced operations that are lock-free and atomic. 
A large set of operations, in an application, can be performed without the need to synchronize most of the code. We need to understand what applies best in a situation and use the right tool for the job. 
We will see an example where first we display how synchronized locking is used in multi-threaded applications to achieve concurrency, and then we will see a solution providing a lock-free solution of the same problem.
The following example shows how synchronization and the locking mechanisms are used as a solution for concurrency. 
Java
// Java Program to demonstrate the // Synchronization of threads// using Locks   import java.io.*;  class GFG {    public static void main(String[] args)        throws InterruptedException    {        // Creating Obj for CountTrees Class         CountTrees countTrees = new CountTrees();                  // Creating Obj for IncreaseTrees Class         IncreaseTrees increaseTreesThread = new IncreaseTrees(countTrees);                  // Creating Obj for IncreaseConcrete Class        IncreaseConcrete increaseConcreteThread            = new IncreaseConcrete(countTrees);                  // Starting both Thread increaseTreesThread         // And increaseConcreteThread by using start method.         increaseTreesThread.start();        increaseConcreteThread.start();                  // Join method Enable threads wait to complete         increaseTreesThread.join();        increaseConcreteThread.join();          // To print the no. of trees by getting current         // value by using countTrees Obj.         System.out.println("Number of trees in your area ::"                           + countTrees.getNumOfTrees());    }}  // Implementation of IncreaseTrees using Threadclass IncreaseTrees extends Thread {      private CountTrees countTrees;      IncreaseTrees(CountTrees countTrees)    {        this.countTrees = countTrees;    }      @Override    public void run()    {        System.out.println("Planting trees in progress...");        countTrees.plantTrees();    }}  // Implementation of IncreaseConcrete using Threadclass IncreaseConcrete extends Thread {      private CountTrees countTrees;      IncreaseConcrete(CountTrees countTrees)    {        this.countTrees = countTrees;    }      @Override    public void run()    {        System.out.println("Concretization in progress...");        countTrees.concretizing();    }}  // Synchronizing the shared resourcesclass CountTrees {      private int trees = 10000;      public synchronized void plantTrees()    {        for (int i = 0; i < 10000; i++)            trees++;    }      public synchronized void concretizing()    {        for (int i = 0; i < 10000; i++)            trees--;    }      public synchronized int getNumOfTrees()    {        return this.trees;    }}
Output:
Planting trees in progress...
Concretization in progress...
Number of trees in your area:: 10000


Now to convert the above example into a simple lock-free sample, we use the AtomicInteger class of Java which is part of the Concurrent package java.util.concurrent.atomic.AtomicInteger. It is a very useful class which can be easily used in concurrent applications as below : 
Java
// Java program to demonstrate to achieve concurrency// with the help of AtomicInteger class which is used// in application like atomically incremented the counter  // Lock Free program for achieving concurrencyimport java.io.*;  // Java provides wrapper class to achieve atomic // operations without the use of synchronization // like java.util.concurrent.atomic.AtomicIntegerimport java.util.concurrent.atomic.AtomicInteger;  class GFG {      public static void main(String[] args)        throws InterruptedException    {        // Creating Obj for CountTrees Class        CountTrees countTrees = new CountTrees();          // Creating Obj for IncreaseTrees Class        IncreaseTrees increaseTreesThread            = new IncreaseTrees(countTrees);          // Creating Obj for IncreaseConcrete Class        IncreaseConcrete increaseConcreteThread            = new IncreaseConcrete(countTrees);          // Starting both Thread increaseTreesThread        // and increaseConcreteThread by using         // start method.        increaseTreesThread.start();        increaseConcreteThread.start();          // join method Enable threads wait to complete        increaseTreesThread.join();        increaseConcreteThread.join();          // To print the no. of trees by getting current        // value by using countTrees Obj.        System.out.println("Number of trees in your area ::"                           + countTrees.getNumOfTrees());    }}  // Implementation of IncreaseTrees classclass IncreaseTrees extends Thread {      private CountTrees countTrees;      IncreaseTrees(CountTrees countTrees)    {        this.countTrees = countTrees;    }      @Override public void run()    {        System.out.println("Planting trees in process...");        countTrees.plantTrees();    }}  class IncreaseConcrete extends Thread {      private CountTrees countTrees;      IncreaseConcrete(CountTrees countTrees)    {        this.countTrees = countTrees;    }      @Override public void run()    {        System.out.println("Concretization in progress...");        countTrees.concretizing();    }}  // Implementation of CountTrees Classclass CountTrees {      // In java AtomicInteger Class provides operations on    // underlying int value that can be read and     // written atomically.    private AtomicInteger trees = new AtomicInteger(10000);      // Implementation of plantTrees method    public void plantTrees()    {        // AtomicInteger class obj trees        // atomically incremented the value.        for (int i = 0; i < 10000; i++)            trees.incrementAndGet();    }    // Implementation of concretizing method    public void concretizing()    {        // AtomicInteger class obj trees        // decremented the value.        for (int i = 0; i < 10000; i++)            trees.decrementAndGet();    }      public int getNumOfTrees()    {        // AtomicInteger class obj        // trees Gets the current        // value.        return trees.get();    }}
Output: 
Concretization in progress...
Planting trees in process...
Number of trees in your area::10000


Summary and Key Takeaways :
The AtomicInteger class is a great tool that can be used in simple applications like concurrent counting and building simple readable code without the complexity of using a lock.
AtomicInteger should be used only when atomic operations are needed. Also, the race condition can still exist between two separate atomic operations.
The AtomicInteger class is on par and can sometimes be more efficient than a regular integer with a lock as protection.
If an application is only using a single thread, the regular integer is preferred.
References: AtomicInteger class in Java
mathurritika
Java-AtomicInteger
Java
Java
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Initialize an ArrayList in Java
Interfaces in Java
ArrayList in Java
Multidimensional Arrays in Java
Singleton Class in Java
Stack Class in Java
Set in Java
LinkedList in Java
Collections in Java
Multithreading in Java