public class Test {
static int i = 1;
public static void main(String[] args) {
new Thread(() -> {
long timer = System.nanoTime();
while (true) {
while (System.nanoTime() - timer > 1E9 / 60) {
i++;
timer = System.nanoTime();
}
}
}).start();
long timer = System.nanoTime();
while (true) {
while (System.nanoTime() - timer > 1E9 / 60) {
System.out.println(i);
timer = System.nanoTime();
}
}
}
}
启动程序时,控制台中将打印以下内容:
1,3,4,5,6
为什么跳过号码2
?我不认为这是一个时间问题。有什么想法吗?
答案 0 :(得分:1)
没有任何同步,这是有效执行的示例(线程1是您创建的线程,线程2是主线程):
Thread 1 Thread 2
i = 2
print i: 2
i = 3
print i: 3
print i: 3 //loop iterates twice in Thread 2
i = 4
i = 5 //loop iterates twice in Thread 1
print i: 5
i = 6
print i: 5 //main thread doesn't see the update
i = 7
print i: 5 //main thread doesn't see the update
请注意,例如,另一个有效的执行是重复打印1。
答案 1 :(得分:1)
输出1,3,4,5,6
似乎不变。它可能因同步不当而有所不同。
阅读器在获取值时打印该值。它并不关心值是否已更新或此值已更新的次数。
作者独立于读者更改值。它并不关心读者阅读的最后一个值。
多线程中存在一个称为the readers-writers problem的常见问题。您重现了这个问题中最简单的问题:一位读者与一位作家。
你并行运行相同的代码片段,可能假设它们可以某种类型" overlay"彼此如下:
while (true) {
while (System.nanoTime() - timer > 1E9 / 60) {
i++;
System.out.println(i);
timer = System.nanoTime();
}
}
不幸的是,它永远不会这样。
没有"happened-before"关系,因此无法保证" increment-then-print" 或" print-then-增量" 模式将始终有效。
答案 2 :(得分:0)
有两个原因:
static int i
变量由两个不同的线程使用
同时由于种族而导致不可预测的行为
条件。用{替换static int i
解决了这个问题
static AtomicInteger i
System.nanoTime() - timer > 1E9 / 60
不会在完全可预测的情况下执行while循环中的代码
次。