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

java:如果总是在锁释放之前调用notify(),那么等待的线程如何获得相同的锁?

子车勇锐
2023-03-14

我想我已经知道这个问题的答案,但是,我想阅读你的意见,以确保我真正理解java线程的状态机(或图表)是如何工作的。

想象线程A在返回给定值之前运行通知():

public class baz{

    // Thread B runs this:
    public synchronized void bar(){
       wait();
    } 

    // Thread A runs this:
    public synchronized int foo(){
       notify();
       return 11;
    }
}

notify()将在线程A释放锁之前调用(这将发生在return 11;语句之后)。那么,线程B(通过wait()方法)如何获得线程a仍然持有的锁呢?注意,当通知线程B时,线程A尚未释放锁。

因此,我对这种情况的看法如下:

调用etc()后,线程B会将其状态从“运行”更改为“等待”。线程B收到通知后(来自线程A通知()方法),会从“等待()”返回,将其状态更改为“可运行”并尝试获取锁。由于线程A尚未释放锁,线程B将在对象的监视器上被阻塞,并将其状态从“可运行”传递给“阻塞”。最终,线程A释放锁后,线程B将获取锁并将其状态从“阻塞”传递给“运行”。

是这样吗?对于这个问题,我想了解的是,从一个wait()返回的线程发生了什么,该线程由已经获取的锁同步。

共有1个答案

南门鸿振
2023-03-14

是的,你的解释是正确的。

当您在对象上调用< code>wait()时,调用线程将被添加到对象的等待集。当它被< code>notify()ied时,它将被从等待集中删除,并对该对象执行锁定操作(它位于该对象上< code>synchronized块内)。那个锁定动作将阻塞当前线程,直到它完成,即。已锁定对象监视器。

这与两个线程尝试在同一对象上输入同步块时的行为完全相同。到达的第一个线程将锁定对象监视器,立即完成锁定对象。其他线程阻塞,直到其锁定操作完成,即。在第一个线程解锁监视器之后。

 类似资料:
  • 我正在编写一个基于await/sleep范式的网络绑定应用程序。 我更喜欢这样一个答案,不创建任何额外的线程

  • 问题内容: 在Java线程转储中,您可以看到堆栈跟踪中提到的锁。 似乎有三种信息: 1: 2: 3: 1:线程已获得对象0x00002aab329f7fa0的锁。 2&3:似乎是说线程正在等待该对象上的锁可用… 但是2和3有什么区别? 问题答案: 使用内在锁时,您将在线程转储中获得“等待锁”,而使用java.util.concurrent中的锁时,将获得“停放以等待”。考虑以下示例: 随着您将获得

  • 如果一个线程已经获取了锁,我希望其他线程跳过获取锁的尝试,只需等待释放锁,然后再继续执行。我不希望其他线程在释放锁后获取它。 我一直在研究这个问题,但仍然感到困惑。 请参阅以下通用代码段: 我怎么能让线程进入我的其他块等待重入锁被解锁之前继续执行?

  • 问题内容: 为什么线程不等待?线程启动,然后进入等待池,但是在那一刻之后它将继续执行。 问题答案: 您正在线程对象本身上进行同步,这是错误的用法。即将发生的事情是,即将死去的执行线程总是调用其对象: 依赖于this。因此,很清楚为什么在其中有或没有自己的情况下都会得到相同的行为。 解决方案:使用单独的对象进行线程协调;这是标准做法。

  • 问题内容: 我有很多代码, 调用时处理器很小,有时会导致性能问题(100毫秒),因此我想知道当前等待对象释放的线程是什么。 我想在调用之前打印所有等待对象释放的线程 问题答案: 是否所有线程都在资源上等待相同的条件?如果是,则可以尝试替换,尽管实际上不建议这样做。AFAIK,无法“检索”在给定对象上等待的所有线程的列表(尽管您可以通过编程方式获取进程的线程转储并查看线程,但是我敢肯定那不是您拥有的

  • 从理论上讲,一个等待线程(假设Thread_1)首先获取一个互斥体,然后通过调用wait()等待条件变量。对wait()的调用会立即解锁互斥体。当另一个线程(比如Thread_2)调用notify()时,等待的线程(Thread_1)被唤醒,相同的互斥体在等待之前被锁定(..)调用返回。 现在假设多个线程在给定的时间等待一个条件变量(假设是Thread_1、Thread_2和Thread_3)。现