public class TestMain {
private static int index = 0 ;
public static void main(String[] args) {
new Thread(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true){
index++;
}
}).start();
new Thread(()->{
int temp = index;
while (true){
if(temp!=index){
System.out.println(index);
temp = index;
}
}
}).start();
}
}
描述:线程1对共享变量index执行++操作,线程2循环去判断index的值是否变化,测试后发现,
情况1:当第线程1中有Thread.sleep(100)时,线程2无法检测到index的值变化,死循环无输出,结果与预计的一致,
情况2:但是注释掉Thread.sleep(100)后,线程2会输出部分后进入死循环。
按照可见性的说法,由于index不是线程安全的,线程2在判断时的取值没有去主内存取最新的值。应该与Thread.sleep(100)没有关系,为什么去掉后反而检测到了部分值变化?
其实从你描述的来说,你这个和线程安全关系不大,你这个和CPU时间片有关,你线程1中有没有Thread.sleep(100)关系不大,主要是 while (true){index++;}这代码。这个线程在执行这个死循环时,它会一直占用CPU,根本不会切换到线程2执行,如果你添加输出或者sleep就能看出效果。while (true){System.out.println(index);index++;}。
简单来说,就是你线程A往杯子里倒水,线程B检测杯子水的量。但是你线程A一直占用杯子,B根本没拿到杯子
而当你线程A中有Thread.sleep(100)时,是线程B先拿到杯子,所以在BSystem.out的瞬间A有机会拿到杯子,如果B没有这句,可能A也没机会
只有等时间片切换才能切换杯子的所有权
两周情况在我电脑都没复现,可能我核数比较多16C