多级Java同步

时间:2014-12-04 08:36:16

标签: java performance synchronization

如下面的示例所示,一旦在call方法中对某个对象进行了锁定,就不需要其他方法来使用synchronized关键字。

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
    }
}

但是,如果我仍然将synchronized关键字添加到furtheronceMore,那么效果会如何影响?或者根本不受影响?

编辑:如果需要锁定或锁定,是否会增加检查成本(遇到synchronized关键字后)?这种检查在内部是否增加了开销?

编辑:应用程序不会只有一个线程,这里的代码只是示例代码。可以用run方法替换main

4 个答案:

答案 0 :(得分:3)

表现不会受到影响。获得已经获得的锁只会带来任何成本。这种技术称为biased locking。默认情况下,启用偏置锁定。这就是为什么单线程应用程序不会受到调用synchronized方法的影响。

Java SE 6 Performance White Paper

  

对象是"有偏见"通过monitorenter字节码或同步方法调用首先获取其监视器的线程;后续的监视器相关操作可以由该线程执行,而不使用原子操作,从而产生更好的性能,特别是在多处理器机器上。

答案 1 :(得分:3)

同步机制使方法稍慢,如果只有一个线程,请尝试不同步方法

答案 2 :(得分:2)

由于JDK 7 HotSpot JVM能够通过消除嵌套锁来优化此类代码。

优化名为-XX:+EliminateNestedLocks,默认情况下处于启用状态。

在JIT编译期间删除了冗余锁,因此即使检查锁是否已被占用,也没有运行时开销。但是,此优化仅在监视对象为static final或锁定this对象时才有效。

答案 3 :(得分:0)

我根据下面的评论修改了基准。
在这个基准测试中,多次获取锁定,偶尔花费的时间比acquire_once少,但我认为这是因为背景线程如gc和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;
        }
    }
}

这里我用jdk1.7编译它(与eclipse编译器的结果是一样的) enter image description here

所以我的结论是有开销。