ZGassassin 2022-04-25 22:50 采纳率: 0%
浏览 18
已结题

为什么操作一个对象中的AtomicInteger不是原子操作

代码如下:
import com.dcy.pojo.Prize;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class TestPrize {
static AtomicInteger atomicInteger = new AtomicInteger(30);
static AtomicInteger atomicInteger1 = new AtomicInteger(0);

static ExecutorService pool = Executors.newFixedThreadPool(5);
static ArrayList<Prize> prizes = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
    Prize p = new Prize();
    p.setActId(74);
    p.setSiteId(1001l);
    p.setPrizeLeft(30);
    prizes.add(p);
    for (int i=0;i<100;i++) {
       pool.execute(new TestCAS());
    }
    Thread.sleep(3000);
    System.out.println("atomicInteger1="+atomicInteger1.get());
}
static class TestCAS implements Runnable {
    @Override
    public void run() {
        for (Prize prize : prizes) {
            if (prize.getActId()==74) {
                int left =-1;
                if( (left=prize.getPrizeLeft().decrementAndGet())>=0){
                    atomicInteger1.incrementAndGet();
                    System.out.println("atomicInteger:"+atomicInteger.decrementAndGet()+"---"+Thread.currentThread().getName()+"left="+left);
                    prize.setPrizeLeft(left);
                }
            }
        }
    }
}

}
代码最后打印出来的atomicInteger1 多半都大于30,并且注意到left有多次打印重复的情况。为什么prize.getPrizeLeft().decrementAndGet()会返回相同的值?

  • 写回答

1条回答 默认 最新

  • ZGassassin 2022-04-25 22:59
    关注

    在Prize中给prizeLeft属性加上volatile关键字也不行,必须得这样用
    AtomicInteger prizeLeft = prize.getPrizeLeft();
    if( (prizeLeft.decrementAndGet())>=0){
    atomicInteger1.incrementAndGet();
    才不会有问题

    评论

报告相同问题?

问题事件

  • 系统已结题 5月3日
  • 创建了问题 4月25日

悬赏问题

  • ¥50 求恶意流量检测系统搭建教程( C++ python C)
  • ¥15 mmseqs内存报错
  • ¥15 vika文档如何与obsidian同步
  • ¥15 华为手机相册里面的照片能够替换成自己想要的照片吗?
  • ¥15 陆空双模式无人机飞控设置
  • ¥15 sentaurus lithography
  • ¥100 求抖音ck号 或者提ck教程
  • ¥15 关于#linux#的问题:子进程1等待子进程A、B退出后退出(语言-c语言)
  • ¥20 web页面如何打开Outlook 365的全球离线通讯簿功能
  • ¥15 io.jsonwebtoken.security.Keys