是否保证线程将按照Java中wait()挂起/阻止的顺序恢复?

时间:2018-02-17 18:46:25

标签: java multithreading concurrency

假设我的程序使用三个线程。使用wait()阻止前两个线程,然后第三个线程恢复并恢复它们。当第三个线程释放两个线程时,它会在这两个线程之间创建竞争条件(如果我错了,请纠正我)。这是我写的一个程序来说明这一点:

class Callee {
    static boolean doBlock = true;
    void callMe (int index) throws InterruptedException {
        //suspend the first two threads
        if (index < 3 && doBlock) {
            wait();
        }

        System.out.println("The index is: " + index);

        //let the third thread resume both of them
        if (index == 3) {
            doBlock = false;
            notifyAll();
        }
    }
}

class Caller implements Runnable {

    final int threadIndex;
    final Thread thread;
    final Callee callee;

    Caller(int index, Callee c) {
        threadIndex = index;
        callee = c;
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        synchronized (callee) {
            try {
                callee.callMe(threadIndex);

            } catch (InterruptedException ie) {
            ie.printStackTrace();
            }
        }
    }
}

public class App {

    public static void main(String[] args) throws InterruptedException {
        Callee c = new Callee();

        Caller caller1 = new Caller (1, c);
        Caller caller2 = new Caller (2, c);
        Caller caller3 = new Caller (3, c);

        caller1.thread.join();
        caller2.thread.join();
        caller3.thread.join();
    }
}

每次我在Windows机器上运行上述程序时,我都会获得一致的输出:

The index is: 3 The index is: 1 The index is: 2

请注意,第一个线程在第二个线程之前被释放。另请注意,我没有为任何这些线程设置优先级。我跑了至少十次,但结果没有改变。我很好奇,如果它是我的操作系统,还是Java总是恢复先被阻止的线程?

2 个答案:

答案 0 :(得分:2)

简短回答

不,不能保证他们会按顺序恢复,所以即使行为多次被多人验证,你也不应该建立任何逻辑,但你有一个很好的想法,而不是只是假设。

长答案

可能发生的是,这就是线程在Windows上的行为方式;如果线程完全由SO本身处理,它甚至可能是特定版本的Windows特有的行为。在这种情况下,由于Java在多个操作系统上工作,并且每个操作系统的行为都不同,因此Java无法保证所有环境中的行为,因此不会对此做出任何承诺。

它也可能只是该特定版本的JVM的行为,而Sun / Oracle从未想要提交特定行为,这意味着即使此行为在当前JVM版本中保持不变,因为它是永远不是正式合同的一部分&#34;他们可以随时保留更改权利,恕不另行通知。

在任何一种情况下,如果您决定在其上构建逻辑,可能会发生的情况是,代码在其他操作系统上无法正常工作,或者甚至更好地在操作系统更新或JVM更新后停止正常工作(即使是次要的)。

这种情况的一个例子发生在我已经工作了几年的公司;过去,Oracle(RDBMS)用于根据GROUP BY标准自动对结果进行排序,如果你没有指定任何标准(它从未成为SQL标准的一部分,也没有在任何Oracle文档中指定,每个人都只是注意到它就像那样工作)......在他们无限的智慧中,许多人开始只是跳过ORDER BY子句,如果他们使用group by。然后出现了一个新的Oracle版本(可能是9i或10g),他们刚刚停止对结果进行自动排序,导致数百万$$$浪费在所有应用程序上进行检查,然后重新进行测试(测试是当然不是自动化的。)

答案 1 :(得分:1)

除非您使用fair lock condition而不是wait/notify,否则不能保证。 您通过synchronized获得的锁定不公平。