首先把代码volitileDemo.put(100);
改成volitileDemo.put(i);
,这样很直观的可以看到当输出到多少时会停止输出.
我这里测试一般是50~200左右.这个应该跟CPU相关.
在停止输出后程序还在运行,由此可以推断进入了死循环了.此时的情况是put线程认为hasNew==true,所以一直在自旋,printNew认为hasNew==false,一直无法进入打印逻辑.这就是由于内存不可见导致两个线程对同一个变量读取到的值不一样,所以导致了两个线程都在死循环中无法解脱.
那么真实的值应该是多少呢?
可以在put方法里的while里加一行System.out.println("xxx"),这个时候你会发现程序就算不加volatile也能断断续续的运行完.这里就证明了是因为put线程读到的值是没有及时更新的值,所以进入了死循环.
那为什么加了sout就可以了呢,我的理解是内存不可见只是代表延迟可见,并不是永久不可见.所以在没有sout的情况两个线程一直在循环,耗费大量CPU,一直无法让CPU去做别的事情,所以缓存得不到刷新.加了sout,线程会进行一些io操作,这样就能让cpu缓一缓去干别的事情了.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…