关于volatile对变量自增不保证原子性的原因所产生的疑问。

在多线程情况下,有i变量:

volatile int i = 0

这种情况下,如果多线程对i进行自增操作:i++,结果可能会与预期值不同,这是什么原因呢?

先来看看大多人对这一错误的解释:
是因为volatile不能保证原子性,而i++其实有三步操作,读,修改,写,并不是原子操作,所以volatile当然不能保证结果的准确性,解释完毕!

其实博主我觉得这种解释相当的流氓
让我想起高中时略带痞气的我应付语文老师的抽问,大概是:
一个选择题,下列选项正确的是:
A.李白 B.杜甫 C.陶渊明 D.汪伦 这道题的答案老师已经说了选C,老师问我:张珂,这道题为什么不选B。
我的回答:因为B是错的。
感谢大家对这一问题应付性的解释,让我回忆起了高中生涯。。。。
这不是废话吗?为什么,人家问的是原因,看着网上博客上的那些解释我真的来气……..

算了,让我来仔细推敲一下,具体是什么原因。
什么是原子性?
下面贴上砖家们的非常详细的解释:
原子性
(1)原子是构成物质的基本单位(当然电子等暂且不论),所以原子的意思代表着——“不可分”;
(2)原子性是拒绝多线程操作的,不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性。例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。

ok,现在我明白了,i++不具备原子性,所以呢,在执行i++的时候,可能会有其他线程让i++执行到一半断掉。
ok,哥今天就跟你杠上了,于是哥再次确认了i++的过程。

i++的过程如下:

1.生成临时变量:                      int temp;  
2.i的值拷贝给临时变量:              temp = i;  
3.i1i = i + 1;  

现在假设有2个线程都执行i++操作(如下代码片所示),照大家所说,因为i++不是原子操作,i被volatile修饰(即保证内存可见性)的情况下,假设Ⅰ线程先执行,无论Ⅰ线程执行到哪一步被打断,Ⅱ线程再执行最后都是到i = i+1;的时候才会改变i的值,而且i的值一旦改变,对另一个线程立马就可见了,i的值永远是最新的,那为什么i++会出错呢?

Ⅰ线程:                  Ⅱ线程:
int temp;  ①           int temp;  ④
temp = i;  ②           temp = i;  ⑤
i = i + 1; ③           i = i + 1; ⑥

唉,看了一下午,网上都没有解释清楚的,问周围人也都不清楚,等大神解答!万分感激!!!

分割线
·································································································································································
更新于 2018.2.1
突然想起 i=i+1;这也不是原子操作啊。。 也就是说 如果上面I线程的代码的 i=i+1 右边的i+1先计算了,还没有来得及赋值给 i 的时候,Ⅰ线程中断,Ⅱ线程更新i的值,这个时候虽然i的值会重新刷新到 Ⅰ 线程中,但是i+1早就被计算了,我猜想 i+1的值应该也是存在某个中间变量中,所以即使 Ⅰ 线 程 立马刷新 i 的值, 但是这个存 i+1 值的中间变量是不会更新的,所以才会造成 volatile修饰的整型变量自增会发生运算错误。

关于 i=i+1; 这个i+1计算了之后是否有个中间变量暂时存着还不知道,有待大佬们求证。或者说i+1的值计算结束是放在常量池了?然后i=i+1;的这个赋值操作,实际上就是i重新指向常量池中的值。应该就是这两种可能,具体哪一种未知,大佬们求证!!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值