gpt4 book ai didi

java - 重新进入同步块(synchronized block)的成本

转载 作者:行者123 更新时间:2023-11-30 05:54:33 25 4
gpt4 key购买 nike

问题:当监视器已经锁定时,重新进入同步块(synchronized block)的成本是多少?

例如:

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

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

上面的意图是当线程在 lock 上同步时,总是调用 innerOneinnerTwo

如果有不可忽略的成本,是否有任何方法可以调用以放入 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 操作系统上)?

凭直觉,我不认为重新进入同步块(synchronized block)会产生明显的成本,因为我能找到的大多数文章都暗示无竞争锁的成本很低。但是,在这些方法中添加同步块(synchronized block)感觉不对,因为它给人的印象是它们可以在没有首先在锁上同步的情况下被调用。 assert 可以更好地理解意图,但它看起来像一个相当丑陋的 hack。我想知道没有更合理的替代方案是否有充分的理由。

最佳答案

所以您的问题是在问一件事,然后您的问题正文是在问另一件事。我可以肯定地说你的算法来测试一个线程是否持有锁会很慢。比不检查要慢得多。像这样抛出异常是昂贵的。关于异常(exception)的第一条规则。 不要在程序中使用异常来进行常规流程控制。异常控制流结构的一种形式,但您应该只将它们用于错误流控制。主要是因为无论何时抛出异常,它都必须收集堆栈跟踪以将其放入异常中。这是一个昂贵的操作。您绝对应该使用异常,但仅限于它们的设计用途:错误流控制。

如果你想测试当前线程是否持有锁,你应该使用 Thread.holdsLock(Object monitor)

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

至于currentThread已经是holder,重新进入synchronize block 的代价是多少。我对此没有非常详细的答案。我怀疑调用 holdLock 的成本是多少。这可能是第一次检查,如果它返回 false,则请求将此线程添加到在此对象监视器上等待的线程列表中会产生更多成本。如果它是真的,它会直接跳入 block 中。 Java线程,如果它想要高性能,这个问题的答案对于锁拥有者来说最好是快得要死。对于不拥有锁的线程来说,它肯定更昂贵。如果有确切算法的答案,我打赌它在“Taming Threads”一书或 Java 规范中。

关于java - 重新进入同步块(synchronized block)的成本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9225744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com