3

下面是我在本地机器上运行时成功完成执行的代码片段。

我不明白为什么这个线程没有进入无限等待状态?

public class Job extends Thread {

    private int counter;

    @Override
    public void run() {
        synchronized (this) {
            for (int i = 0; i < 100000; i++) {
                counter++;
            }

            this.notifyAll();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Job job = new Job();
        job.start();
        synchronized (job) {
            job.wait();
        }

        System.out.println(job.counter);
    }
}

是否有任何保证上述代码将始终在每种情况下完成执行?有人可以澄清吗?

4

4 回答 4

1

确实看起来Race Condition您手上有一个-这完全取决于哪个synchronized(job)先发生-主线程中的那个或工作中的那个。

于 2013-09-14T18:35:42.853 回答
0

有几种可能

  1. 主线程进入第synchronized一个和wait()s。在这种情况下,程序将终止,因为将job Thread调用对象。notify()synchronized
  2. 首先job Thread进入synchronized块并notify()在主要调用之前Thread调用wait(),即。mainThread不能,因为它在synchronized街区等待。这将阻止应用程序,因为主程序Thread将无法从wait()调用中返回。
于 2013-09-14T18:33:59.957 回答
0

除了虚假的唤醒问题(大多数情况下不会影响这种简单的使用),您应该期望该代码始终完成。

您似乎缺少的一件事是job.wait();释放锁,使另一个synchronized块能够被执行和notifyAll()被调用。此时,wait唤醒并退出主要方法。

于 2013-09-15T08:34:24.823 回答
0

我不明白为什么这个线程没有进入无限等待状态?

this.notifyAll()它可以,并且如果在之前调用它就会发生job.wait()

添加一个标志来测试是否完成,如下所示:

public class Job extends Thread {

    private int counter;
    private boolean finished = false;

    @Override
    public void run() {
        synchronized (this) {
            for (int i = 0; i < 100000; i++) {
                counter++;
            }

            finished = true;
            this.notifyAll();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Job job = new Job();
        job.start();
        synchronized (job) {
            while (!job.finished)
                job.wait();
        }

        System.out.println(job.counter);
    }
}

这样你就可以保证程序不会进入竞争状态并且会永远等待。另请注意,您现在可以防止虚假唤醒

于 2013-09-14T19:23:05.907 回答