volatile 为什么不保证原子性
能演示下 volatile 为什么不保证原子性吗?
原子性:一个操作或一系列操作是不可分割的,要么同时成功,要么同时失败。
这个定义和 volatile 啥关系呀,完全不能理解呀?Show me the code!
考虑一下这种场景:
当 20 个线程同时给 number 自增 1,执行 1000 次以后,number 的值为多少呢?
在单线程的场景,答案是 20000,如果是多线程的场景下呢?答案是可能是 20000,但很多情况下都是小于 20000。
示例代码:
复制代码
执行结果:第一次 19144,第二次 20000,第三次 19378。
我们来分析一下 increase()方法,通过反编译工具 javap 得到如下汇编代码:
复制代码
number++其实执行了3条指令
:
getstatic:拿 number 的原始值 iadd:进行加 1 操作 putfield:把加 1 后的值写回
执行了 getstatic 指令 number 的值取到操作栈顶时,volatile 关键字保证了 number 的值在此时是正确的,但是在执行 iconst_1、iadd 这些指令的时候,其他线程可能已经把 number 的值改变了,而操作栈顶的值就变成了过期的数据,所以 putstatic 指令执行后就可能把较小的 number 值同步回主内存之中。
总结如下:
在执行 number++这行代码时,即使使用 volatile 修饰 number 变量,在执行期间,还是有可能被其他线程修改,没有保证原子性。
版权声明: 本文为 InfoQ 作者【悟空聊架构】的原创文章。
原文链接:【http://xie.infoq.cn/article/891d9c4ae76fec796aa9c358e】。未经作者许可,禁止转载。
评论