Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multithreading multiple locks seem slower than single lock

I was reading on multithreading in Java and using synchronized blocks. Suppose I have two different, independent synchronized blocks. I can have them run in parallel, by using a lock each for both the synchronized blocks. But if I use the same lock for both synchronized blocks, I think only one can run at a given time. Am i wrong to think so? If no, why am I getting the below strange result?

Assume I have two independent operations, increment1 and increment2, called by a different thread each.

public class AppMultipleSynchronization {

    private static int counter1 = 0;
    private static int counter2 = 0;

    private static Object lock1 = new Object();
    private static Object lock2 = new Object();

    public static void increment1() {
        synchronized (lock1) {
            counter1++;
        }
    }

    public static void increment2() {
        synchronized (lock2) {
            counter2++;
        }
    }

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100000000; i++) {
                    increment1();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100000000; i++) {
                    increment2();
                }
            }
        });

        long startTime = System.currentTimeMillis();

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endTime = System.currentTimeMillis();

        System.out.println("total time taken: " + (endTime - startTime) + "ms");
        System.out.println("counter1: " + counter1 + "\ncounter2: " + counter2);
    }
}

As you can see, I am using a different lock for for both increments. To use the same lock, use the exact same program, replace with lock1 in both cases.

Output in case of two locks:

    total time taken: 13437ms
    counter1: 100000000
    counter2: 100000000

Output in case of single lock:

    total time taken: 5139ms
    counter1: 100000000
    counter2: 100000000
like image 618
keemahs Avatar asked Jul 14 '21 04:07

keemahs


1 Answers

am i wrong to think so? if no, why am i getting the below strange result?

No you are not wrong. If you are using 2 locks then 2 threads can be executing the 2 different blocks at the same time.

What you are seeing is most likely because these sorts of fine grained, threaded, performance tests are very subtle. This may have much more to do about branch and lock prediction than about true runtime. The JVM makes guesses about whether a lock should be tested in a spin loop versus a true mutex wait/queue. It can dramatically optimize this code given that the actual work is just ++. It may also be that t1.start() starts and runs so fast that it finishes before the t2.start() can be executed.

If you change the lock body to be more substantial, you should start to see that the 2 locks will result in faster wall clock runtime. For example, if you do a loop of ++ operations in the block:

public static void increment1() {
    synchronized (lock1) {
        for (int i = 0; i < 100000000; i++) {
            counter1++;
        }
    }
}
...
public void run() {
    for (int i = 0; i < 10000; i++) {
        increment1();
    }
}

Then with 1 locks I get:

total time taken: 62822ms
counter1: -727379968
counter2: -727379968

but 2 locks gets:

total time taken: 30902ms
counter1: -727379968
counter2: -727379968

Lastly, the JVM does a whole bunch of class loading, gcc -O3 equivalence, and machine code inlining during the first seconds and even minutes of runtime. Anytime you are trying to run Java performance tests, you need to make sure your program is running for a long time to get some level of accurate numbers.

like image 73
Gray Avatar answered Nov 15 '22 13:11

Gray