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

带有等待和通知的Java多线程

鲁博雅
2023-03-14

我有一段代码

public MultiThreadedSum(ArrayBuffer ArrayBufferInst)
{
    this.ArrayBufferInst = ArrayBufferInst;
    Sum = 0;
    Flag = false;
    StopFlag = false;
}

public synchronized void Sum2Elements()
{

    while(Flag)
    {
        try {wait();}
        catch (InterruptedException e){}
    }

    Flag = true;

    if (StopFlag)
    {
        notifyAll();
        return;
    }

    System.out.println("Removing and adding 2 elements.");

    Sum = ArrayBufferInst.Sum2Elements();

    notifyAll();
}

public synchronized void InsertElement()
{

    while(!Flag)
    {
        try {wait();}
        catch (InterruptedException e){}
    }

    Flag = false;

    if (StopFlag)
    {
        notifyAll();
        return;
    }

    System.out.println("Inserting the sum.");

    ArrayBufferInst.InsertElement(Sum);

    if (ArrayBufferInst.RetunrSize() == 1)
    {
        StopFlag = true;
    }

    System.out.println(ArrayBufferInst);

    notifyAll();
}

如您所见,我首先将标志设置为false,这样其中一个线程就可以进入Sum2Elements方法并将其更改为true,从而让所有人都等待。

我知道在同步代码中,只有一个线程可以完成它的任务,这里我有两个同步方法,这是否意味着两个线程在每次通知之后都在尝试执行这个方法?

如果是这样,那么一个线程是否不可能输入Sum2Elements,在另一个线程进入InsertElement之前将标志更改为true,从而跳过while循环

谢谢

共有3个答案

巫英纵
2023-03-14

一次只能执行两个方法中的一个,因为两个方法都是同步的,尽管顺序未定义

正如我所说,一次只能由一个线程执行一个方法,除非执行线程通过调用wait方法释放lock,而其他线程获得lock并执行其他synchronized方法,这使您的两条语句都成为可能。

高运诚
2023-03-14

锁是在类的对象上获得的

如果希望两个不同的线程同时访问这些同步方法,那么这两个线程应该在类的两个不同对象上操作。

柴正祥
2023-03-14

只有一个线程可以持有对象的锁。然后只有那个线程可以在该对象上输入同步方法。

然而,线程可以通过调用对象释放锁,而无需从方法返回。等等()。

所以你的代码看起来不错!

does it mean that 2 threads are trying to conduct this methods after each notifyall? 
Ans : It is very much possible for two threads to be in two of your synchronized methods since you are calling wait().

is it not possible for one thread to enter Sum2Elements, change the flag to true before the other thread enters InsertElement, and by that skipping the while loop?
Ans : Yes this is possible again for the same reason specified above.
 类似资料:
  • 我想做一个小练习来习惯等待/通知。我想做的是简单地启动一个线程,然后用等待让它进入睡眠状态,用通知唤醒它,多次。 我的代码是: 我希望这会是这样 相反,这样做: 所以。。。通知似乎没有唤醒打印机线程? 这不应该是一个死锁,因为通过等待,我释放了所有的锁,所以主服务器不应该有任何对打印机的锁,打印机应该能够唤醒并打印。 我做错了什么?

  • 问题内容: 我写了一个永远不会停止的测试应用程序。它发出(是一个对象),但是我从不打电话通知。为什么此代码结束?尽管主线程在上同步,但生成的线程仍在运行,因此不会锁定该对象。 结果是主线程等待5秒钟,在此期间工作人员提供其输出。然后,在5秒钟后,程序退出。不等。如果主线程在5秒钟内没有进入睡眠状态(对此行进行了注释),则实际上将等到工作人员完成操作。当然,这里是一种使用方法,但是,出乎意料的是,它

  • 因为这是我的第一篇文章,所以我为它的结构上的任何错误道歉。我正在做一个个人项目,这是一个用java制作的时钟,可以显示时间/日期/日期,每季度播放一个音频文件,以及报时。图形用户界面是用摆动项构建的。 当时钟到达一定时间时,它必须发出钟声/播放声音,我希望在时钟响起时在GUI上显示一个图标。此时,图标在方法的开头切换,在方法的结尾再次切换。在第二次切换图标之前,我希望方法在播放音频时等待()。(也

  • 我不完全理解和()是如何工作的,因此我不得不将尝试缩减到以下代码部分。 main.java: runner.java: 当前,我在调用时得到一个非法MonitorStateException,但我不明白为什么。从我所看到的情况来看,我需要同步,但在这样做的时候,我假设它只会通知一个线程,而我的想法是通知所有线程。 我已经查看了,但是我找不到合适的替换(也许我只是遗漏了一些东西)。

  • 问题内容: 我知道您可以使用lock在c#中锁定对象,但是可以放弃该锁并等待其他东西来通知您它已更改,就像您可以在Java中使用wait和notify一样吗? 在我看来,分别在Java和C#中同步和锁定是同义的。 问题答案: 等效功能(包括常规锁定)在Monitor类中。 C#中的语句等效于调用并带有适当的try / finally块。 有关更多详细信息,请参见我的线程教程或Joe Albahar

  • 我对通知方法的一点感到困惑。“notify() :它唤醒一个在同一对象上调用 wait() 的线程。因此,假设两个线程称为等待同一对象。那么当我调用通知时,将通知哪个线程?