这是关于测试的问题。我已经多次运行代码并得到相同的答案:999999.他们说这个代码每次都不会产生相同的结果,即使在编写runLoop方法时存在synchronized。我错过了什么?
public class B extends Thread{
static int a = 0;
public static void main(String[] Args){
B MyB = new B();
MyB.start();
runLoop(1000000);
System.out.println(a);
}
public static synchronized void runLoop(int b){
for(int i = 0; i<b; i++){
a=i;
}
}
public void run(){
runLoop(12345678);
}
}
答案 0 :(得分:1)
通常在你打电话时
SomeThread.start();
正确启动线程需要一些时间,这允许执行此命令的线程执行其下一行中的一些,例如
SomeThread.start();//lets say it should print "A"
System.out.print("B");
在许多情况下会打印BA
而不是AB
,这就是您的问题所在。
因此,如果您的代码在MyB
线程start()
之前,主线程可以调用自己的runLoop(1000000);
。然后MyB
可以运行runLoop(12345678);
但是现在主线程可以执行System.out.println(a);
,它以非同步的方式访问a
,因此它可以显示MyB
在当前迭代的次数a
时间点(因此两个线程同时访问999999
,每次运行应用程序时可能会产生不同的结果。)
如果您声称自己总是得到回复MyB.start();
,那么您非常幸运,或者没有向我们展示您的真实代码(例如runLoop(1000000);
和MyB.start()
之间的情况其他代码可能需要足够的时间让TimeUnit.SECONDS.sleep(1);
完成proc rollon {boxes args} {
foreach box $boxes {
eval {$box yview} $args
}
}
}。
答案 1 :(得分:0)
您错过了 无法 通过多次运行来证明您的代码具有确定性的事实。但 可以 证明它不是确定性的。这就是编写多线程代码的问题:根据个人偏见来解释结果太容易了。我们都这样做。
此处还有其他内容:代码通过start方法间接调用runLoop(),这是正确的, 和 代码直接调用runLoop()主要方法。这就是为什么代码不是确定性的 - 这是原始问题的答案。 main方法中对runLoop()的显式调用不应该存在。所有主要的应该是踢开线程。
答案 2 :(得分:0)
在推断线程安全问题时,很可能它适用于您的计算机。或者在许多机器上,在正常情况下。但这并不意味着该程序正常工作。实际上,“总是”工作的代码可能会在某些条件下中断。
答案 3 :(得分:0)
这里有两件事 -
单线程模型 - 要确保获得值999999,您应该限制线程同时访问它。在这种情况下,它的主线程和一个正在启动。您可以按照前面的答案中的建议同步课程{{1}}。
多线程模型 - 因为您只有同步的类的实例,所以仍可以同时访问类级资源。在此输出中保证始终相同。