2012-02-10 27 views
2

问题:当显示器已被锁定时,重新进入同步块的开销是多少?重新进入同步块的开销

例如:

Object lock; 
void outer() 
{ 
    synchronized (lock) 
    { 
     innerOne(); 
     innerTwo(); 
    } 
} 

void innerOne() { synchronized (lock) { /* ... */ } } 
void innerTwo() { synchronized (lock) { /* ... */ } } 

的上述意图是innerOneinnerTwo而线程上lock同步总是调用。

如果存在不可忽略的成本,是否有任何方法可以调用以放入assert声明?我能找到的最接近的电话号码是lock.notify(),以及IllegalMonitorStateException,例如

boolean isMonitorHeld(final Object object) 
{ 
    try { object.notify(); return true } 
    catch (final IllegalMonitorStateException e) { return false; } 
} 

哪想被使用:

void innerOne() { assert isMonitorHeld(lock); /* ... */ } 

有没有对两个选项的样式任何意见或任何替代方案?

编辑

我希望更全面的答案不仅仅是“时间,看看”。我没有能力预见我的代码可能遇到的所有潜在情况,然后创建一个测试来展示这些情况。我想了解同步机制如何工作以了解它在不同情况下如何执行。我知道同步可能在不同的平台上以不同的方式实现。在哪种情况下有所不同(主要在Solaris和Linux操作系统上)?

直觉上,我不认为重新进入同步块会有明显的成本,因为我发现的大多数文章都暗示无连锁锁是便宜的。但是,在这些方法中添加同步块并不合适,因为它给人的印象是它们可以被称为,而不是首先在锁上同步。断言提供了一个更好的想法,但它看起来像一个相当丑陋的黑客。我想知道是否有一个很好的理由,没有一个更合理的选择。

+1

你为什么不测量它?如果你*不能测量差异,那么就没有差别。 – skaffman 2012-02-10 09:47:53

回答

4

所以你的问题是要求一件事,然后你的问题的主体是要求别的。我可以肯定地说你的算法来测试一个线程是否持有锁定会非常缓慢。比没有检查慢很多。抛出像这样的例外是昂贵的。关于例外的规则之一。 请勿在程序中使用例外进行常规流量控制。异常控制流结构的一种形式,但您应该只将它们用于错误流量控制。主要是因为每当你抛出一个异常时,它必须收集堆栈跟踪以将其放入异常。这是一项昂贵的操作。您应该明确地使用异常,但仅限于它们的设计目的:错误流控制。

如果你想测试currentThread是否持有一个锁,你应该使用Thread。holdsLock(对象监视器)

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#holdsLock(java.lang.Object

至于什么是重新进入到用于currentThread一个同步块中的成本已经是一个保持器。我没有一个非常详细的答案。我怀疑它调用holdLock的成本是多少。这可能是第一次检查,如果它返回false,则请求将此线程添加到等待此对象监视器的线程列表中的代价更大。如果它是真的,它会跳到块中。 Java线程,如果它想要高性能的话,这个问题的答案对于锁的拥有者来说应该更快。对于不拥有锁的线程来说,它肯定更昂贵。如果有什么确切算法的答案,我可以在“Taming Threads”或Java规范中下注。

+0

谢谢,我完全错过了Thread方法。重点是我有两个或多个方法之间的共享逻辑。初始方法提供了同步,然后执行共享逻辑。从我的经验来看,断言对于描述(在代码中)开发人员的意图很有用。在我的情况下,实际上再次在监视器上同步给出了错误的印象,因为它意味着可以在不首先获得锁的情况下调用该方法。如果没有首先获取锁,该方法就不会被调用,所以如果这样做的话,这是一个编程错误。 – SimonC 2012-02-13 08:30:01

+0

我重读了你的问题,我想它更清楚一点。你只是想知道你是否可以在这两种方法中使用assert语句,而不是像第一部分代码那样重新获得锁定。 – chubbsondubs 2012-02-13 14:28:21

+0

如果方法是公开的,我不会这么做,但是对于使用assert的私有方法来说,会强制调用者锁定,所以如果某人重构了代码,那么如果他们忘记了锁,就会被捕获。我敢打赌,我敢打赌,它与使用同步块相同。 – chubbsondubs 2012-02-13 14:36:18

2

衡量它。在我的系统上可能没有区别。在你的身上可能会有。您部署的系统可能仍然更加不同。