Java Synchronization at Multiple Levels

As shown in the example below, once the lock is performed on an object in a method call

, there is no need for additional methods to have a synchronized keyword.

public class Prac
{ 
    public static void main(String[] args)
    {
      new Prac().call();
    }

    private synchronized void call()
    {
      further();
    }

    private synchronized void further()
    {
      oneMore();
    }

    private synchronized void oneMore()
    {
      // do something
    }
}

      

But if I still add the keyword synchronized

to further

and onceMore

, how will performance impact? Or did they not influence at all?

EDIT : Does it add validation overhead (after a synchronized keyword is encountered) if locking or locking is required? Does this check internally add overhead?

EDIT : The app won't have just one thread, this code here is just sample code. can be replaced by main with run method

+3


source to share


4 answers


Performance will not be affected. It costs nothing to acquire a lock that has already been acquired. This method is called offset locking . Blocking is enabled by default. For this, single-threaded applications are not affected by calls to synchronous methods.

Java SE 6 Performance White Paper :



The object is "biased" to a thread that first receives its monitor via monitor bytecode or a synchronized method call; subsequent monitor-related operations can be performed by this thread without using atomic operations, resulting in significantly better performance, especially on multiprocessor machines.

+3


source


Mechanism

synchronization makes the methods a bit slower, so try not to synchronize the method if you only have one thread



+3


source


Since the JDK 7 HotSpot JVM is able to optimize such code by eliminating nested locks.

Optimization is named -XX:+EliminateNestedLocks

and enabled by default.

Reserved locks are JIT compiled, so there is no runtime overhead even to verify that the lock has already been taken. However, this optimization works only when the monitoring object is static final

or when the object is locked this

.

+2


source


I changed the benchmark as per the comment below.
In this test, acquiring the lock multiple times takes less time from time to time than capture_once, but I think it is because of background threads like gc and jit

public class Benchmark {
    final int count = 10000;
    boolean the_bool = false; // prevent no-op optimization inside the loop

    public static void main(String[] args) {
        Benchmark benchmark = new Benchmark();
        benchmark.start();
    }

    public void start() {
        //run the test 12000 times
        for (int i = 0; i < 12000; i++) {
            long start = System.nanoTime();
            aqcuire_lock_multiple_times();
            long end = System.nanoTime();
            long time1 = end - start; // time to acquire lock multiple times

            start = System.nanoTime();
            acquire_lock_once();
            end = System.nanoTime();
            long time2 = end - start; // the time to acquire lock once
            if (time1 <= time2) {
                String m = MessageFormat.format(
                "time1:{0}ns < time2:{1}ns, iteration:{2}", time1, time2, i);
                System.out.println(m);
            }else{
                // acquire the lock once is faster as expected
            }
        }
    }

    public synchronized void aqcuire_lock_multiple_times() {
        for (int i = 0; i < count; i++) {
            synchronized (this) {
                the_bool = !the_bool;
            }
        }
    }

    public synchronized void acquire_lock_once() {
        for (int i = 0; i < count; i++) {
            the_bool = !the_bool;
        }
    }
}

      

Here I am compiling it with jdk1.7 (results with eclipse compiler are the same) enter image description here

So I came to the conclusion that there is an overhead.

0


source







All Articles