1.实验:
类1:Stock作为库存类,代码为
public class Stock {
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void reduction(){
if(this.getCount()>0){
this.setCount(this.getCount()-1);
}
}
}
类2:线程类
public class TestThread implements Runnable {
private Stock stock;
CountDownLatch latch;
public TestThread(Stock stock,CountDownLatch latch){
this.latch=latch;
this.stock=stock;
}
@Override
public void run() {
stock.reduction();
latch.countDown();
}
}
类3:启动类
public class VolatileTest {
public static void main(String[] args) throws Exception{
CountDownLatch latch = new CountDownLatch(1000);
Stock stock=new Stock();
stock.setCount(1000);
int threadNum=1000;
for (int i = 0; i < threadNum; i++) {
Thread th=new Thread(new TestThread(stock,latch));
th.start();
}
latch.await();
System.out.println("========================"+stock.getCount());
}
}
运行结果:
========================1
========================4
========================0
这个原因大多数同学都清楚,多线程线程不安全导致的。主要出现这种结果的原因有两个:
1.线程之间的不可见性,线程副本不能及时同步到共享内存中。这个可以查看之前的一篇java多线程指令重排序引发的脏读
2.线程运行的原子性,有些操作不是一下完成的
比如i++,其实经过了三个过程,第一步先从共享内存中读取i到自己的线程副本中,然后进行加操作,最后写入到线程。这中间可能因为CPU调度发生中断。比如读取i后,cpu被调度到执行其他线程了,过一会来调回来执行,在这中间i可能已经被修改了,但是线程副本中还是之前的值。