Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多级Java同步_Java_Performance_Synchronization - Fatal编程技术网

多级Java同步

多级Java同步,java,performance,synchronization,Java,Performance,Synchronization,如下面的示例所示,一旦在call方法中锁定了一个对象,就不需要进一步的方法具有synchronized关键字 public class Prac { public static void main(String[] args) { new Prac().call(); } private synchronized void call() { further(); } private synchronized v

如下面的示例所示,一旦在
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
关键字添加到
further
onceMore
,性能会受到怎样的影响?还是根本不受影响

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


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

性能不会受到影响。获取一个已经获取的锁不需要任何成本。这种技术被称为。默认情况下,启用偏置锁定。这就是为什么调用同步方法不会影响单线程应用程序

:

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


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

我根据下面的注释修改了基准。
在此基准中,多次获取锁,有时比一次获取锁花费的时间更少,但我认为这是因为像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;
        }
    }
}
公共类基准{
最终整数计数=10000;
boolean the_bool=false;//防止循环内无操作优化
公共静态void main(字符串[]args){
基准=新基准();
benchmark.start();
}
公开作废开始(){
//运行测试12000次
对于(int i=0;i<12000;i++){
长启动=System.nanoTime();
aqcuire_lock_多次();
long end=System.nanoTime();
long-time1=end-start;//多次获取锁的时间
start=System.nanoTime();
获取_lock_once();
end=System.nanoTime();
long-time2=end-start;//获取锁一次的时间

如果(time1,因为JDK 7 HotSpot JVM能够通过消除嵌套锁来优化这些代码

该优化称为
-XX:+EliminatenestLocks
,默认情况下处于启用状态


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

不会出现任何此类性能问题。但是,只有当您ant直接调用其他方法。应用程序的可能副本不会只有一个线程,这里的代码只是示例代码。可能会将main替换为run方法。因此,我们必须对不希望并行处理的每个方法使用synchronized。对象是“有偏差的”对于首先通过monitorenter字节码或同步方法调用获取其监视器的线程,该线程可以执行后续的监视器相关操作,而无需使用原子操作,从而获得更好的性能,特别是在多处理器机器上,锁定除向w对象“有偏差”将导致一个相对昂贵的操作,从而取消偏差。消除原子操作的好处必须超过取消的惩罚,此优化才能有利可图。
对象“有偏差”的线程之外的线程的锁定尝试将导致一个相对昂贵的操作
这可能会导致问题,不确定是否需要偏置锁定?分析表明,大多数应用程序的大部分时间锁都是由同一线程获取的。如果您的情况不是这样,您可以禁用偏置锁定或在这样的特定位置使用ReentrantLock。它不会不要使用有偏锁定。你把有偏锁和递归锁混淆了。最初的问题是关于递归锁。HotSpot JVM有默认启用的
-XX:+EliminatedLocks
优化,无论
-XX:+UseBiasedLock
启用与否,也不管程序是单线程还是不是。你的基准不正确。