当前位置: 首页 > 知识库问答 >
问题:

可重入同步块内的Java等待/通知

西门马鲁
2023-03-14

我对Java同步()块的理解是,如果一个线程已经拥有一个对象上的锁,它可以进入一个在同一个对象上同步的不同块(重入同步)。下面,我相信JVM使用引用计数来增加/减少线程获得锁的次数,并且锁只有在计数为零时才会释放。

所以我的问题是,如果你遇到这样的代码:

synchronized(this)
{
    if (condition == WAITING)
    {
        synchronized(this)
        {
            condition = COMPLETE;

            notify();

            try
            {
                wait();
            }
            catch(InterruptedException  e)
            {
            }
        }
    }
    else
        condition = READY;
}

当调用etc()时,具体会发生什么?它仅仅是减少计数,还是不顾计数释放锁?

在第一种情况下,在我看来,如果发生了锁重新进入,它将产生死锁,因为它仍然拥有锁,因此将永远在等待它的另一个线程上等待。

在第二种情况下,我根本看不出第二个同步块的点是什么。

wait()的文档说

"当前线程必须拥有此对象的监视器。线程释放此监视器的所有权,并等待,直到另一个线程通知等待此对象监视器的线程通过调用通知方法或通知方法唤醒。线程然后等待,直到它可以重新获得监视器的所有权并恢复执行,"

所以我认为第二个案例是正确的,但我可能错了。那么,我是遗漏了什么,还是仅仅遇到了一个冗余的同步块,可以很容易地从代码中删除?

共有1个答案

雍宇定
2023-03-14

没有什么需要在if之后重新获取锁。

wait()。

我能看到的第二个synchronized的唯一原因是它以前使用了另一个对象,有人错误地修改了它以使用相同的this

 类似资料:
  • 问题内容: 如果我仅使用同步而不是等待/通知方法,它将仍然保持线程安全吗? 有什么不同 ? 提前谢谢。 问题答案: 使用使方法/块一次只能在线程上访问。因此,是的,它是线程安全的。 这两个概念是结合在一起的,而不是相互排斥的。使用时,您需要在该对象上拥有监视器。所以您需要在此之前。使用使当前线程停止,直到另一个线程在其等待的对象上调用。这是对的补充,它仅确保仅一个线程将进入块/方法。

  • 问题内容: 如果一个块上有多个线程在等待,并且锁变为可用,谁先走?是按线程优先级(然后是先到先得)进行吗? 并且是否适用相同的规则(带有多个ing线程)? 问题答案: 根据这个家伙的说法:http : //tutorials.jenkov.com/java-concurrency/starvation-and- fairness.html Java对顺序不做任何保证。所以我想这不是基于线程优先级的

  • 我想更多地了解线程睡眠解析是如何工作的,以及它与睡眠()解析之外的内容有什么联系。 我知道它是由操作系统定义的,而在Windows上通常是15ms。我最近环顾四周无法确认这一点,但我依稀记得这个15ms是由操作系统循环的,并且对所有线程都是“全局的”,这意味着15ms不是线程可以Hibernate的最短时间,而是最大Hibernate时间(1)。对吗?所有操作系统都一样吗(超过持续时间)? 我想不

  • 问题内容: 据我所知,并已替换为更好的并发机制。那么,对于实现同步队列,您会选择哪种更好的替代方法呢? 它们究竟在什么意义上“更好”? 编辑 :这(“实现同步队列”)是一个采访问题。可接受的答案不能使用BlockingQueue或其他队列实现。但是,它可能使用其他同步构造,例如CountDownLatch。我没有允许和禁止的类的详尽列表- 请您注意。 问题答案: 已被Lock类方法和Conditi

  • 任务或任务 我们也可以定义自己的可实现对象。对象应具有以下资格。 < li >它有一个GetAwaiter()方法(实例方法或扩展方法); < li >其GetAwaiter()方法返回一个Awaiter。在下列情况下,对象是一个标识符: < ul > < li >它实现INotifyCompletion或ICriticalNotifyCompletion接口; < li >它有一个IsCompl

  • 我有这个简单的例子给我的控制器,并没有像预期的那样工作 输出:开始、结束、中间 期望:开始、中间、结束