This question already has answers here:
Difference between Synchronized block with wait/notify and without them?

(6 个回答)


5年前关闭。




我试图理解在访问共享资源或依赖它们的状态时通过使用 wait()notify() 来实现线程的必​​要性。

我看到这个想法是监视对象并等待它们的可用性并在使用后释放它们以使它们可用于其他线程/方法,但是为什么这些方法是必要的,而不是仅仅将相关对象声明为静态 volatile 以便其他线程在不调用这些方法的情况下了解状态的变化?

例如

在一家餐厅,有 2 名厨师。其中一位厨师是一名好厨师(更好的 cooking 质量,..)并带有 boolean 值 isGoodCook = true ,而第二位厨师是一名坏厨师并带有 boolean 值 isGoodCook = false

一次只有一名厨师可以做饭的设备。
坏厨师在特定的时间(= cooking 时间)做饭,而好厨师偶尔会进入厨房,接管坏厨师的 cooking 任务。好厨师在他的 cooking 过程中是永远不会被打断的,一旦他开始,他的整个 cooking 时间都会做饭。

(只要好厨师负责做饭,坏厨师就会停止做饭(= 好厨师的 cooking 时间))。

而在好厨师停止做饭后,坏厨师又要重新开始做饭的任务。
private boolean cooking; //is equipment used at the moment
private boolean isGoodCook;
private boolean cookingDesire; //indicating to chef to stop cooking
private int cookingTime;


public CookingTask(boolean isGoodCook, int cookingTime)
{
    this.isGoodCook = isGoodCook;
    this.cookingTime = cookingTime;
}

public void run()
{
    if(isGoodCook)
    {
        //notify actual cook to stop cooking
        cookingDesire = true;
    }
    //wait til equipment to cook
    //is available
    while(cooking)
    {
        try
        {
            wait();
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    //reserve equipment
    cooking = true;
    cookingDesire = false;
    //notify other threads (= bad cook)
    notifyAll();
    startCooking();
}

private void startCooking()
{
    for(int i = 0; i < cookingTime; cookingTime--)
    {
        try
        {
            Thread.sleep(1000);
            //if good chef comes in
            if(cookingDesire)
            {
                //bad chef starts to pause
                startBreak();
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    cooking = false;
}

public void startBreak()
{
    //bad chef stops cooking
    cooking = false;
    notifyAll();
    //measure break time of bad chef
    long stopCookingTime = System.currentTimeMillis();
    while(cookingTime > 0 && cooking)
    {
        try
        {
            wait();
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    int pausedTime = toIntExact((System.currentTimeMillis() - stopCookingTime)/1000);
    //calculate remaining cookingTime
    cookingTime -= pausedTime;
    cooking = true;
    notifyAll();
}

也许有人有时间通读并简要概述我对多线程监控/wait()notify() 的误解,我将不胜感激!

最佳答案

static 意味着一个类的所有对象共享该数据。您认为如何使用静态字段来说明特定线程对象的状态?

我想可以摆脱等待/通知;一种方式是一个线程必须查询其他线程的属性。但这意味着“Activity ”:“等待”线程必须进行轮询。当然,您不能不断轮询,因此您希望它 hibernate 特定时间。这……几乎和等待一样,但更复杂,因为您必须通过编写代码来管理所有细微的细节。

有了等待/通知,你就有了一个推送模型。如果一个线程需要等待;你告诉它这样做;然后,当时间到了,它就会被唤醒。这是一个非常清晰、直接的语义。

所以,当你提出一个不同的模型来解决这个问题时;您确实必须证明您的模型实现了相同的目标;除此之外,计算该模型的额外好处。

10-07 12:09