Nitin Verma’s Blog

Posts Tagged ‘non-blocking

Using jdk 1.6 the cost of blocking synchronization is nearly same as
non-blocking counter part. This does not say 1.6 makes it liveness
hazard free or deadlock free.

But makes it quite fast.

// We have three methods
// -1: Thread unsafe
    public static void addUnsafe() {
        b++;
    }
// 0: Thread safe, non-blocking synchronization
    public static void addNBSync() {
        try {
            lock.lock();
            b++;
        } finally {
            lock.unlock();
        }
    }
// 1: Thread safe, blocking synchronization
    public static synchronized void addSync() {
        b++;
    }

// Log format
//Use:<method>:<end value of b>:<time taken>
$ ~/usr/local/jdk1.5.0_17/bin/java -classpath classes1.5  edu.nitin.Main
Use:-1:63929500:156367000
Use:0:100000000:5360473000
Use:1:100000000:24290461000

$ echo "scale=10; ( 5360473000 - 156367000 ) / 156367000 " | bc
33.2813573196
$ echo "scale=10; ( 24290461000 - 156367000 ) / 156367000 " | bc
154.3426298387

$ ~/usr/local/jdk1.6.0_11/bin/java -classpath classes1.6  edu.nitin.Main
Use:-1:59050465:190538454
Use:0:100000000:5350310972
Use:1:100000000:6404364288

$ echo "scale=10; ( 5350310972 - 190538454 ) / 156367000 " | bc
32.9978353361
$ echo "scale=10; ( 6404364288 - 190538454 ) / 156367000 " | bc
39.7387289773

A test running 1000 threads doing 100,000 atomic operations each,

all the three ways.

...

package edu.nitin;

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

/**
 *
 * @author Nitin Verma
 */
public class Main {

    private final static Lock lock = new ReentrantLock();

    private static long b = 0;
    private final static long n = 100000;
    private final static int a = 1000;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws InterruptedException {
        test(-1);
        test(0);
        test(1);
    }

    private static void test(final int use) throws InterruptedException {
        b = 0;
        final long start = System.nanoTime();
        long end = 0;
        try {
            final Thread[] ta = new Thread[a];
            for (int i = 0; i < a; i++) {                 ta[i] = new Thread(new MyRunnable(use));                 ta[i].start();             }             for (int i = 0; i < a; i++) {                 if (ta[i] != null && ta[i].isAlive()) {                     ta[i].join();                 }             }         } finally {             end = System.nanoTime();         }         System.out.println("Use:" + use + ":" + b + ":" + (end - start));     }     public static void addN(final long n, final int use) {         if (use == 0) {             for (long i = 0; i < n; i++) {                 addNBSync();             }         }         else if (use == 1)  {             for (long i = 0; i < n; i++) {                 addSync();             }         }         else {             for (long i = 0; i < n; i++) {                 addUnsafe();             }         }     }     public static void addNBSync() {         try {             lock.lock();             b++;         } finally {             lock.unlock();         }     }     public static synchronized void addSync() {         b++;     }     public static void addUnsafe() {         b++;     }     private static class MyRunnable implements Runnable {         private int use;         public MyRunnable(final int use) {             this.use = use;         }         public void run() {             addN(n, use);         }     } } [/sourcecode]

Advertisements