假设我的程序使用三个线程。使用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总是恢复先被阻止的线程?
答案 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)