带有昂贵参数的Java同步方法

时间:2013-11-29 14:03:00

标签: java synchronization

我有一个出现的同步方法使用'同步显着长于它应该。它看起来像;

public static synchronized void myMethod(MyParameter p) {
    //body (not expensive)
}

电话看起来像;

myMethod(generateParameter());

已知generateParameter()是一个非常昂贵(需要很长时间)的电话。我的想法是myMethod类的互斥锁在执行generateParameter()期间被阻止了这是怎么回事?我发现它是一个不同的调试问题,但这似乎正在发生。

5 个答案:

答案 0 :(得分:5)

那不可能;首先执行generateParameter()调用,然后将其结果作为myMethod调用的参数给出,然后获取互斥锁。

需要很长时间,还是无限期阻止? (僵局)

答案 1 :(得分:5)

不,不会发生什么。

在调用generateParameter之前执行方法myMethod

在Java中,所有方法参数始终在方法调用之前进行评估。

specification of method call详细解释了这一点(感谢Victor Sorokin)。

  

在运行时,方法调用需要五个步骤。首先,可以计算目标参考。其次,评估参数表达式。第三,检查要调用的方法的可访问性。第四,找到要执行的方法的实际代码。第五,创建新的激活帧,如果需要则执行同步,并且将控制转移到方法代码。

除了新变量之外,您的代码与下面的代码相同:

MyParameter p = generateParameter();
myMethod(p);

答案 2 :(得分:2)

执行myMethod的线程在方法开头进入对象的监视器并保持它直到它退出。在方法内完成的任何操作都是synchronized,但是在调用之前会评估所有调用参数,因此generateParameter不会在myMethod的锁定窗口内执行。

如果generateParameter上有任何同步,它可能会争用同一个锁,因为没有明确的同步对象,JVM会在调用其方法的对象上进行同步。

我强烈建议对代码进行分析,以确定它真正陷入困境的位置。

答案 3 :(得分:1)

而不是static synchronized void myMethod(p)更好地使用ReadWriteLock作为您的资源:

MyParameter p = generateParameter();

myMethod(p){

  ReadWriteLock readWriteLock = new ReentrantReadWriteLock();


  readWriteLock.readLock().lock();

    // multiple readers can enter this section
    // if not locked for writing, and not writers waiting
    // to lock for writing.

  readWriteLock.readLock().unlock();


  readWriteLock.writeLock().lock();

    // only one writer can enter this section,
    // and only if no threads are currently reading.

  readWriteLock.writeLock().unlock();
}

答案 4 :(得分:0)

“在执行generateParameter()期间,myMethod类上的互斥锁被阻止”

据我所知,只有在generateParameter函数执行结束后才会获取锁。