背景
我正在阅读一份技术文档,主要介绍在fori循环中使用int和long的区别:
场景A(使用int的fori循环)
public class SafePoint {
public static AtomicInteger num = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Runnable runnable=()->{
for (int i = 0; i < 1000000000; i++) {
num.getAndAdd(1);
}
System.out.println(Thread.currentThread().getName()+"end!");
};
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println("num = " + num);
}
}
期望结果:
线程1结束!
线程0结束!
num = 2000000000
场景B(长for循环)
public class SafePoint {
public static AtomicInteger num = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
Runnable runnable=()->{
for (long i = 0; i < 1000000000; i++) {
num.getAndAdd(1);
}
System.out.println(Thread.currentThread().getName()+"end!");
};
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println("num = " + num);
}
}
期望结果:
num = 55406251(或小于2000000000的某个随机数)
Thread-1结束!
Thread-0结束!
他提出的最重要的概念是安全点: 由于未计算循环而在long fori循环中有安全点,但int fori循环中没有安全点。因此,在int fori循环中,睡眠需要等待两个线程完成,然后进行GC,因为当线程仍在int fori循环中时没有安全点。
问题:
我采纳了他的想法并尝试在本地机器上再现它们,但失败了: 基本上无论我使用int还是long,结果都与第二个类似。num首先被打印出来。
经过仔细思考后,只能归结于我使用的JVM:java 11 corretto。
根据技术文档的想法,这基本上意味着在Java 11中,安全点存在于计算和未计算的循环中
相关链接:
技术文档试图解释和如何在fori循环中进行GC:为什么Thread.sleep(0)可以防止火箭MQ中的gc?