【问题标题】:Why object is not lock while thread is in runnable status?为什么线程处于可运行状态时对象未锁定?
【发布时间】:2016-04-09 18:23:23
【问题描述】:

我有跑步课。很简单,只需打印、休眠然后打印;

    public class Run implements Runnable {

    @Override
    public void run() {
        System.out.println("START RUN");
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("FINISH RUN");
    }
}

好的,现在我正在编写测试;

public static synchronized void main(String[] args) throws InterruptedException {

        Run r = new Run();
        Thread t = new Thread(r, "TEST");
        t.start();

        // EXECYTE THE CODE WHULE THREAD "TEST" IS RUNNABLE 
        synchronized (t) {
            System.out.println(t.getState());
            t.wait();
        }
        System.out.println("Y");

        // SLEEP THREAD "TEST" TO BE EXECUTED DURING THE TIME
        Thread.sleep(100);
        synchronized (t) {
            System.out.println(t.getState());
            t.wait();
        }
        System.out.println("Y2");
    }

问题 1: 当线程“TEST”正在执行时,我尝试等待()。 此时线程状态为“RUNNABLE”。由于这种状态,它确实等待,我不明白为什么?如果状态为“TERMINATED”或“NEW”,wait() 有效;如果我删除 t.start(),线程状态将是“新”,所以等待也有效。你能告诉我会发生什么吗?

输出:

START RUN
RUNNABLE
FINISH RUN
Y
TERMINATED`

【问题讨论】:

  • 快速提问:你认为t.wait() 在做什么?
  • 这仅显示线程启动时的状态。 Thread.sleep 不锁定任何东西。
  • 使当前线程等待,直到另一个线程调用 notify 或 notifyAll。当 t.wait() 被执行时,首先,线程处于休眠状态,因此它不会等待。但是在线程将被执行后它被挂起

标签: java multithreading


【解决方案1】:

这是相当糟糕的记录。 Thread#join(long) 的 javadoc 状态

当线程终止时,this.notifyAll 方法被调用。 是 建议应用程序不要使用waitnotifynotifyAll on Thread 个实例。

它特别是说不要做你目前正在做的事情。也就是说,synchronizedThread 对象上调用 wait 在同一对象上。

synchronized (t) {
    System.out.println(t.getState());
    t.wait();
}

在您的代码的当前执行中。当您的 TEST 线程处于休眠状态时,您的主线程会到达上面的 t.wait() 调用。 TEST 然后唤醒并终止。当它终止时,它调用notifyAllt.wait() 唤醒你的主线程。

当你的主线程到达第二个t.wait() 时,你的程序中没有任何东西可以唤醒它,所以你的程序只是挂起。


所有这些都是要说的:不要将Thread 对象监视器用于任何事情

【讨论】:

  • 为了清楚起见,“推荐”的意思是“永远不要这样做”。 :) 真的没有。只是不要。
  • 我不明白; :( 当线程“TEST”此时正在休眠时 t.wait() 被调用并且 - 它没有挂起。我不明白为什么。如果线程被终止或新线程挂起。
  • 如果它被终止或新的(未启动),它不会调用notifyAll,所以不会从第一个t.wait()唤醒主线程。
  • 您可以使用任何对象作为监视器并调用monitor.wait(),调用线程将等待,直到另一个线程调用同一个监视器实例notify 或notifyAll。然后等待线程将继续。
  • 因为 Thread 类将 notifyAll 用于特殊用例,所以不应将其用作监视器对象。
猜你喜欢
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 2013-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多