【问题标题】:Thread example - notify() before wait()?线程示例 - 在等待()之前通知()?
【发布时间】:2019-11-27 15:51:03
【问题描述】:

我有以下线程示例:

class TickTock {
    String state; // contains the state of the clock

    synchronized void tick(boolean running) {
        if(!running) { // stop the clock 
            state = "ticked";
            notify(); // notify any waiting threads 
            return;
        }
        System.out.print("Tick ");
        state = "ticked"; // set the current state to ticked
        notify(); // let tock() run 
        try {
            while(!state.equals("tocked"))
                wait(); // wait for tock() to complete 
        }
        catch(InterruptedException exc) {
            System.out.println("Thread interrupted.");
        }
    }

    synchronized void tock(boolean running) {
        if(!running) { // stop the clock 
            state = "tocked";
            notify(); // notify any waiting threads 
            return;
        }
        System.out.println("Tock");
        state = "tocked"; // set the current state to tocked
        notify(); // let tick() run 
        try {
            while(!state.equals("ticked"))
                wait(); // wait for tick to complete 
        }
        catch(InterruptedException exc) {
            System.out.println("Thread interrupted.");
        }
    }
}

class MyThread implements Runnable {
    Thread thrd;
    TickTock ttOb;

    // Construct a new thread. 
    MyThread(String name, TickTock tt) {
        thrd = new Thread(this, name);
        ttOb = tt;
        thrd.start(); // start the thread 
    }

    // Begin execution of new thread. 
    public void run() {

        if(thrd.getName().compareTo("Tick") == 0) {
            for(int i=0; i<5; i++) ttOb.tick(true);
            ttOb.tick(false);
        }
        else {
            for(int i=0; i<5; i++) ttOb.tock(true);
            ttOb.tock(false);
        }
    }
}

class ThreadCom {
    public static void main(String args[]) {
        TickTock tt = new TickTock();
        MyThread mt1 = new MyThread("Tick", tt);
        MyThread mt2 = new MyThread("Tock", tt);

        try {
            mt1.thrd.join();
            mt2.thrd.join();
        } catch(InterruptedException exc) {
            System.out.println("Main thread interrupted.");
        }
    }
}

mt2 怎么在等 mt1 呢?是不是因为 mt1 是在 mt2 之前创建的,所以先进入同步方法?如果是 - 下一个问题是:为什么 mt1 在 wait() 之前调用 notify()?不调用wait()如何释放监听?

我是这样理解的:mt1:我不能在这里做更多的工作,所以我会等待()然后我通知()mt2。

现在,当我写这篇文章时,我意识到调用 wait() 的线程可能不能再调用任何其他方法?所以也许这就是为什么需要先调用 notify() 的原因?

谁能给我解释一下?谢谢!

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    mt2怎么在等mt1呢?

    mt2 将状态设置为“tocked”后,它会一直等到它变为“ticked”。只有mt1 可以做到这一点。

    是不是因为mt1先于mt2创建,所以先进入同步方法?

    哪个线程先进入方法并不重要。如有必要,每个人都会等待另一个人。如果可以前进的线程首先获得锁,它会前进。如果错误的线程获得了锁,它只会等待另一个线程,释放锁并允许该线程继续前进。

    如果是 - 下一个问题是:为什么 mt1 在 wait() 之前调用 notify()?

    由于mt 已更改state 并且另一个线程可能正在等待状态更改,因此调用notify 很重要。首先调用wait 将是一场灾难——另一个线程可能正在等待收到有关该线程所做更改的通知,而两个线程相互等待是死锁。

    不调用wait()如何释放监听?

    不可能。但这没关系。线程将在完全完成或等待另一个线程时释放监视器。在所有其他情况下,它会主动修改共享状态并且您不希望释放锁。

    【讨论】:

    • 我用简单的程序开始线程。我用同步方法创建了类。该方法由两个或多个线程执行,我知道该方法需要同步,因为两个线程同时使用它。现在我有一个具有两种不同方法的对象 - 那么为什么它们需要同步呢?能否请您向我解释一下 2 首印中发生了什么?
    • 我很困惑,因为我认为两个线程同时进入 tick() 和 tock() 所以前两个打印(“Tick Tock”)只是关于命令顺序的问题,因为当您进入该方法时,tick() 和 tack() 都无法控制正在执行的线程。所以 System.out.println(Tick/Tack) 都可以在线程进入它们时执行。当每个线程执行自己的方法时,为什么 mt1 或 mt2 需要相互等待?
    • @vviston 代码的目的是演示如何处理线程到达某个点的情况,直到另一个线程到达某个点才能继续前进。
    • 我意识到我无法理解当时只有一个线程正在执行同步方法的概念。我认为两个线程可以使用相同的对象方法,但是根据 Oracle,当线程执行对象的方法之一时,对象被完全锁定。我不知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 2020-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多