3

As shown in example below, once lock is taken on an object in call method, there is no need for further methods to have 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 synchronized keyword to further and onceMore, how will performance be impacted? Or not impacted at all?

EDIT : Does it add costs of checking(after encountering synchronized keyword) if it has lock or lock is required? Internally does this checking adds overhead?

EDIT : application will not have one thread only, this code here is just sample code. may be replace main with run method

codingenious
  • 8,385
  • 12
  • 60
  • 90
  • There will not be any such performance issue. However its required only when you want to call other methods directly. – janasainik Dec 04 '14 at 08:40
  • 1
    possible duplicate of [Biased locking in java](http://stackoverflow.com/questions/9439602/biased-locking-in-java) – Mikhail Dec 04 '14 at 08:43

4 Answers4

3

The performance will not be impacted. Acquiring a lock, which is already acquired costs nothing. This technique is called biased locking. By default biased locking is switched on. That's why single thread applications are not impacted by calling synchronized methods.

Java SE 6 Performance White Paper:

An object is "biased" toward the thread which first acquires its monitor via a monitorenter bytecode or synchronized method invocation; subsequent monitor-related operations can be performed by that thread without using atomic operations resulting in much better performance, particularly on multiprocessor machines.

Mikhail
  • 4,175
  • 15
  • 31
  • An object is "biased" toward the thread which first acquires its monitor via a monitorenter bytecode or synchronized method invocation subsequent monitor-related operations can be performed by that thread without using atomic operations resulting in much better performance, particularly on multiprocessor machines Locking attempts by threads other that the one toward which the object is "biased" will cause a relatively expensive operation whereby the bias is revoked. The benefit of the elimination of atomic operations must exceed the penalty of revocation for this optimization to be profitable. – codingenious Dec 04 '14 at 08:51
  • 1
    `Locking attempts by threads other that the one toward which the object is "biased" will cause a relatively expensive operation` May be this will cause problem, not sure if biased locking is what is required? – codingenious Dec 04 '14 at 08:52
  • Analysis showed that most of the time locks are acquired by the same thread for most applications. If this is not true for your case you can disable biased locking or use ReentrantLock in such specific place. It does not employ biased locking AFAIK. – Mikhail Dec 04 '14 at 08:56
  • 1
    You are confusing *biased* locks with *recursive* locks. The original question is about *recursive* ones. HotSpot JVM has `-XX:+EliminateNestedLocks` optimization which is turned on by default, no matter whether `-XX:+UseBiasedLocking` enabled or not and no matter if the program is single-threaded or not. – apangin Dec 04 '14 at 20:17
3

synchronization mechanism make methods a little bit slower so try to not synchronize method if you have only one thread

void
  • 7,760
  • 3
  • 25
  • 43
  • application will not have one thread only, this code here is just sample code. may be replace main with run method. – codingenious Dec 04 '14 at 08:46
  • so we have to use **synchronized** for each of methods that we don't want to processed parallel – void Dec 04 '14 at 08:59
2

Since JDK 7 HotSpot JVM is capable of optimizing such code by eliminating nested locks.

The optimization is called -XX:+EliminateNestedLocks and is turned on by default.

The redundant locks are removed during JIT-compilation, so there is no run-time overhead even to check if the lock is already taken. However this optimization works only when monitor object is static final or when locking this object.

apangin
  • 92,924
  • 10
  • 193
  • 247
0

I modified the benchmark according to the comment below.
In this benchmark, acquiring the lock multiple times, occasionally takes less time than acquire_once, but I think this 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 compile it with jdk1.7 (the results with eclipse compiler are the same) enter image description here

So my conclusion is that there is overhead.

outdev
  • 5,249
  • 3
  • 21
  • 38
  • You benchmark is incorrect. [How do I write a correct microbenchmark](http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java). – apangin Dec 04 '14 at 19:59