关于原子类中getAndAddInt方法

skping-go 2020-05-15 10:19:17


这个是老师讲的一个图,但是我感觉,有些不理解的地方,。

个人感觉是不是应该把两个圈的位置换一下,也就是,如果数据发生了改变,其实是var5为未改变的值0,var1为改变后的值1,预期返回值为1是错误的,所以进入下一次循环。
...全文
556 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
skping-go 2020-05-17
  • 打赏
  • 举报
回复
引用 1 楼 亦夜 的回复:
这两个不可以交换,CAS主要就在于比较并交换,前提就是要有一个原始值以及期望值,当这两者相同时,你才能改变,这里的交换不是指var1和var5进行交换,就比如你说的var5为0,var1为改变后的1,那var1改变的条件是什么?var1改变的前提就是var1和var5是相同的情况下,其实这个很好理解,你本来有个0,你执行++操作,但是底层会判断,你当前给我的期望值是不是0,是的话,我才给你++,不是我就不加,其实getAndIncrement方法看的不是很清晰,你可以看一下,AtomicStampedReference类的compareAndset方法体现的清楚
大概原理都懂,就是不知道getAndIncrement方法中,v1和v5哪个代表可能会改变改变的值。就是说,正常情况下,都是0,但是被其他线程把值加1之后,使两个值不一致,是v1变成了1,还是v5变成了1.
亦夜 2020-05-17
  • 打赏
  • 举报
回复
引用 2 楼 skping-go 的回复:
[quote=引用 1 楼 亦夜 的回复:] 这两个不可以交换,CAS主要就在于比较并交换,前提就是要有一个原始值以及期望值,当这两者相同时,你才能改变,这里的交换不是指var1和var5进行交换,就比如你说的var5为0,var1为改变后的1,那var1改变的条件是什么?var1改变的前提就是var1和var5是相同的情况下,其实这个很好理解,你本来有个0,你执行++操作,但是底层会判断,你当前给我的期望值是不是0,是的话,我才给你++,不是我就不加,其实getAndIncrement方法看的不是很清晰,你可以看一下,AtomicStampedReference类的compareAndset方法体现的清楚
大概原理都懂,就是不知道getAndIncrement方法中,v1和v5哪个代表可能会改变改变的值。就是说,正常情况下,都是0,但是被其他线程把值加1之后,使两个值不一致,是v1变成了1,还是v5变成了1.[/quote] 你这个理解其实是有那么一点偏差的,为什么说CAS能保证原子性,就是因为类似乐观锁的机制,你A线程把数据从0改成了1,但是我B线程也要去修改它,但是B的期望值是什么?B持有的还是0所以期望0(没有加volatile的前提下),但是在主内存中数据已经变成了1,所以比较失败,此次修改作废,B线程需要重新去主内存中更新值,看到这里你可能还是不怎么明白,v1和v5都会变,但是v1变得是要修改的数据,而v5变得是一个类似版本号,比如你的操作不是加1 ,而是每次加10,那么第一次v1从0变成10,那么表示执行成功了一次操作,v5的版本号加1,如果B线程也想要修改,那它就必须拿最新的版本号1才能修改这个v1,不然修改失败
亦夜 2020-05-16
  • 打赏
  • 举报
回复
这两个不可以交换,CAS主要就在于比较并交换,前提就是要有一个原始值以及期望值,当这两者相同时,你才能改变,这里的交换不是指var1和var5进行交换,就比如你说的var5为0,var1为改变后的1,那var1改变的条件是什么?var1改变的前提就是var1和var5是相同的情况下,其实这个很好理解,你本来有个0,你执行++操作,但是底层会判断,你当前给我的期望值是不是0,是的话,我才给你++,不是我就不加,其实getAndIncrement方法看的不是很清晰,你可以看一下,AtomicStampedReference类的compareAndset方法体现的清楚

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧