此代码来自样本OCP / SCJP
我不确定为什么在run()之前调用Printx()。 为什么这有保证?
public class ConstructorOrRun extends Thread {
private int x = 2;
public ConstructorOrRun() throws Exception {
x = 5;
start();
}
public void printX() throws Exception {
x = x - 1;
System.out.print(x);
}
public void run() {
x *= 2;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
new ConstructorOrRun().printX();
}
}
答案 0 :(得分:4)
我不认为'保证'在这里是正确的词。实际上,printx可能会先完成,因为starting a new thread takes a huge amount of time相对于当前运行的线程执行litle算术所花费的时间,获得控制台的(无竞争)锁并写入它。
但这是一种竞争条件,依靠先发生的事情是一个非常糟糕的主意。如果程序运行足够多次,则可能发生各种交错。这里不能保证会发生什么事情,最好避免做出假设。
还有另一个问题。构造函数由主线程调用,初始化x,然后启动新线程。新线程在run方法中修改x,但是没有任何要求使新内容对x的内容可见。制作x volatile会使其内容可见。
另一个问题是:算术运算需要执行多个步骤,并且可能受到另一个线程的干扰。这不仅仅是一个操作首先会发生的问题,它们可能是交错的。修复此问题需要锁定或使用atomicInteger。
答案 1 :(得分:3)
ConstructorOrRun()立即在主线程上返回,然后调用printX()。
在构造函数返回之前,无法保证在构造函数中调用start()会导致run()启动,更不用说完成(在不同的线程上)。事实上,如果确实如此,我会感到惊讶。