AtomicInteger类真的是线程安全的嘛??

wozuiqiangdeaoyi 2014-03-16 01:04:15
public final int incrementAndGet() {
for (;;) {
int current = get();//1
int next = current + 1;//2
if (compareAndSet(current, next))//3
return next;
}
}
以上是源代码,这个操作相当于i++

如果有两个AtomicInteger,i1和i2,i1执行到步骤2,自己栈中的值变成5,没有执行步骤3,因为步骤3才是是写操作,所以此时i1自己的栈中的值是加1后的5,但是主内存中的值还是4,此时i2通过get()得到当前主内存的值,4,进行加1操作,变成5.

到此,i1和i2在他们各自的栈中都是5,现在他们把5这个值写回主内存,i1成功了,它执行的是compareAndSet(4, 5);
i2在执行步骤3的时候,执行的也是compareAndSet(4, 5);但是,此时主内存中第一个参数对应的值已经被i1改成5,所以此次操作失败,i2进入第二个循环,通过步骤1获得当前值5,然后加1,所以最后i2把值变成了6.

如果i2的线程中代码是这样的:
if (i2 == 4)
{
i2.incrementAndGet();//预期是5,但是实际上是6
}
对嘛?
...全文
1541 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
天边tbdp 2016-09-02
  • 打赏
  • 举报
回复
atomicInteger本身是线程安全的,肯定能得到自己想要的结果,结果是正确的
daker_129 2016-01-22
  • 打赏
  • 举报
回复
好像似的,以前用多线程i++,发现总数不对,换了之后就ok了
piaopiao11 2016-01-21
  • 打赏
  • 举报
回复
整个方法本身并不是线程安全的,但通过compareAndSet方法,可以达到安全操作的效果。 lz分析是对的,从中可以看出,如果并发量大,则循环次数会显著增多,从而会大量占用cpu时间, 不过由于没有加线程同步锁,整个操作的线程开销比较小的,很多时候也会提高线程执行的效率。
hy200304 2016-01-21
  • 打赏
  • 举报
回复
关键是这个函数compareAndSet,先比较Native保存的值如果相等才会Set新值,要不然就会return false,继续下次循环,重新取值。这个其实是线程安全的。
wozuiqiangdeaoyi 2014-03-17
  • 打赏
  • 举报
回复
引用 2 楼 dring321 的回复:
楼主的意思是,i1和i2共用一个内存地址。能否把代码贴出来共享下
代码就是: public final int incrementAndGet() { for (;;) { int current = get();//1 int next = current + 1;//2 if (compareAndSet(current, next))//3 return next; } } 其中gei()就是简单的return value; compareAndSet(current, next)是一个底层cpu指令,让cpu线程安全的增加一个值,但是可能会失败,返回类型是boolean
代码间的舞者 2014-03-17
  • 打赏
  • 举报
回复
楼主的意思是,i1和i2共用一个内存地址。能否把代码贴出来共享下
结贴是美德 2014-03-16
  • 打赏
  • 举报
回复
对对对对对对对对

62,634

社区成员

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

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