Sunday, June 11, 2017

Multiple Locks to enhance application performance

Multiple Locks ; Using synchronized code blocks

public class Worker {
     private Random random = new Random();

     List<Integer> list1 = new ArrayList<Integer>();
     List<Integer> list2 = new ArrayList<Integer>();

     /* Thread 1 possess worker object lock while entering stageOne , thus thread2 can't enter stageTwo
      * although both threads are manipulating different data of an object */
    
     /*synchronized void statgeOne() throws InterruptedException {
     list1.add(random.nextInt(100));
     Thread.sleep(1);
     }

     synchronized void stageTwo() throws InterruptedException {
     list2.add(random.nextInt(100));
     Thread.sleep(1);
     }
      */

     /*Solution - We could have two different objects invoking different methods at once */
     Object obj1 = new Object();
     Object obj2= new Object();
    
     void statgeOne() throws InterruptedException {
           synchronized (obj1) {
                list1.add(random.nextInt(100));
                Thread.sleep(1);
           }
     }

     void stageTwo() throws InterruptedException {
           synchronized (obj2) {
                list2.add(random.nextInt(100));
                Thread.sleep(1);
           }
     }
     void process() throws InterruptedException{
           for(int i=0;i<1000;i++){
                statgeOne();
                stageTwo();
           }
     }
    
     public void main() throws InterruptedException {
           System.out.println("Starting ....");
          
           long start = System.currentTimeMillis();
          
           Thread t1= new Thread(new Runnable() {
                @Override
                public void run() {       
                try {
                     process();
                } catch (InterruptedException e) {
                     e.printStackTrace();
                     }
                }
           });
          
           Thread t2= new Thread(new Runnable() {
                @Override
                public void run() {       
                try {
                     process();
                } catch (InterruptedException e) {
                     e.printStackTrace();
                }
                }
           });
           t1.start();
           t2.start();
           t1.join();
           t2.join();
          
           long end = System.currentTimeMillis();
           System.out.println("List 1 size"+ list1.size()+"List 2 size "+ list2.size());
           System.out.println("Time taken :"+(end-start));
     }
}

Output

Starting ....
List 1 size 2000 
List 2 size 2000
Time taken :2862



Atomic Operations in java7

Atomic Operations without using java.util.concurrent.atomic package

class Counter {
      int count;

      public synchronized void increment() {
            count++;
      }

      public int getCount() {
            return count;
      }
}

public class NonAtomicOperation extends Thread {
      private Counter counter;

      public NonAtomicOperation(Counter counter) {
            this.counter = counter;
      }

      public static void main(String[] args) throws InterruptedException {
            Counter counter = new Counter();
            NonAtomicOperation thread1 = new NonAtomicOperation(counter);
            NonAtomicOperation thread2 = new NonAtomicOperation(counter);
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(counter.getCount());
      }

      public void run() {
            for(int i=0;i<1000;i++)
                  counter.increment();
            }
}

Here, we’ve counter object being shared by two threads at once. If synchronized not being used then output won’t be 2000

Please note that count++ isn’t an atomic operation.  So by the time one threads read it's value and increment it by one, other thread has read the older value leading to wrong result.

One way to make it right is by using synchronized keyword, so that one thread at a time access increment() and using join() as well so as to stop main thread to print the value right away.

Second Approach
Here is the updated program that will always output count value as 2000 because AtomicInteger method incrementAndGet() atomically increments the current value by one.

class Counter {
      AtomicInteger count = new AtomicInteger();

      public void increment() {
            /* incrementAndGet() atomically increments the current value by one*/
            count.getAndIncrement();
      }

      public int getCount() {
            return count.intValue();
      }
}

public class NonAtomicOperation extends Thread {
      private Counter counter;

      public NonAtomicOperation(Counter counter) {
            this.counter = counter;
      }

      public static void main(String[] args) throws InterruptedException {
            Counter counter = new Counter();
            NonAtomicOperation thread1 = new NonAtomicOperation(counter);
            NonAtomicOperation thread2 = new NonAtomicOperation(counter);
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(counter.getCount());
      }

      public void run() {
            for (int i = 0; i < 1000; i++)
                  counter.increment();
      }
}

Output:
2000

Advantages


Benefits of using Concurrency classes for atomic operation is that we don't need to worry about synchronization. This improves code readability and chance of errors are reduced. Also atomic operation concurrency classes are assumed to be more efficient that synchronization which involves locking resources.

Saturday, June 10, 2017

Scenarios where Synchronized can get tricky

Everyone knows advantage of using synchronized keyword in java that they help in concurrency and atomicity but there are some scenarios where synchronized can get tricky.

Example 
package com.java5;

/* Ground rule - Access to static field should be done using static Synchronized method
 *         Access to non-static field should be done using non-static Synchronized method
*/
public class StaticNonStaticSynchronzied {

     /*************** Scenario 1*******************/
     /* Here static synchronized and non static synchronized won't block each other */
    
     static int b;
    
     /* Multiple threads can invoke staticMethod() and nonStaticMethod() simultaneously changing b value*/
    
     /* Thread 1 invoking using class object*/
     synchronized static void staticMethod(){
          b++;
     }
    
     /* Thread 2 invoking using this object*/
     synchronized  void nonStaticMethod(){
          b++;
     }
    
     /********************** Scenario 2******************/
     static int c;
    
     /*Multiple threads might invoke below method using different locks and accessing same static field*/
     synchronized  void nonStaticMethod1(){
          c++;
     }
}

Ground Rule

Ideally access to static field should be done and in scope within static synchronized method and access to non-static field should be done and in scope within non-static synchronized method

Put your comments below what do you think of these scenarios and how can you prevent it. STAY LEARNING