volatile int i=0;
if(i==0)
i=1;
i++;
单一的写操作和读操作 都是原子操作,但是i++不是原子操作,即使加了volatile,也不能保证其原子性。
volatile 可以保证 可见性 和 有序性,但是无法保证 原子性。
利用 javap 反编译,i++ 的字节码如下
假若两条线程 同时执行 i++ 假设i=5
1)线程 A,B 同时把执行 getfield 指令把 i 的值拷贝到各自的操作栈中;volatile 保证了这个值的可见性。
2) 线程 A,B 同时执行 iconst_1 将int类型的1推送至栈顶。
3)线程 A 执行完 iadd 并且 putfield ,此时 得到 temp = i+1,得到temp=6 ,并将temp的值传给主存中的i(6),然后线程B的拷贝得到的i失效; 但是此时线程B已经执行完了temp= i+1,不需要计算,但是temp(6)仍然是未自增的i+1,再进行 i=temp(6) ,导致少加了一。