我有一个出现的同步方法使用'同步显着长于它应该。它看起来像;
public static synchronized void myMethod(MyParameter p) {
//body (not expensive)
}
电话看起来像;
myMethod(generateParameter());
已知generateParameter()
是一个非常昂贵(需要很长时间)的电话。我的想法是myMethod
类的互斥锁在执行generateParameter()
期间被阻止了这是怎么回事?我发现它是一个不同的调试问题,但这似乎正在发生。
答案 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
函数执行结束后才会获取锁。