Java 并发中的原子类
1. 为什么需要原子类多线程环境下有个常见问题publicclassCounter{privateintcount0;publicvoidincrement(){count;}}count看似一行代码实际分三步读取 count 的值加 1写回 count多线程下可能发生线程A读取 count0 线程B读取 count0 线程Acount1写回 线程Bcount1写回 // 线程A的结果被覆盖了最终 count1但实际应该等于 2。2. 解决办法synchronized 加锁publicsynchronizedvoidincrement(){count;}缺点性能差每次只能一个线程进入。原子类privateAtomicIntegercountnewAtomicInteger(0);publicvoidincrement(){count.incrementAndGet();}一行搞定性能比 synchronized 高很多。3. 常用原子类AtomicIntegerAtomicIntegercountnewAtomicInteger(0);// 加1count.incrementAndGet();// icount.getAndIncrement();// i// 减1count.decrementAndGet();// --icount.getAndDecrement();// i--// 加任意值count.addAndGet(5);// 获取值intvaluecount.get();// 设置值count.set(100);// CAS 操作count.compareAndSet(100,200);// 如果当前值是100则设置为200AtomicLong和 AtomicInteger 用法一样只是类型不同AtomicLongcountnewAtomicLong(0);count.incrementAndGet();AtomicBooleanAtomicBooleanflagnewAtomicBoolean(false);// 设为 trueflag.set(true);// CAS 操作flag.compareAndSet(false,true);AtomicReference用来原子更新对象AtomicReferenceUseruserRefnewAtomicReference();Useruser1newUser(张三,20);Useruser2newUser(李四,25);userRef.set(user1);userRef.compareAndSet(user1,user2);// 如果当前是 user1则改为 user24. 数组原子类// 数组中某个元素原子操作AtomicIntegerArrayarrnewAtomicIntegerArray(newint[]{1,2,3});arr.getAndAdd(0,10);// 第一个元素加10intvaluearr.get(0);// 获取第一个元素5. 累加器jdk8 新增的比 AtomicInteger 性能更高专门用于累加场景LongAddercountnewLongAdder();count.add(1);count.increment();longvaluecount.sum();内部原理是把一个值拆成多个 Cell减少竞争。适合高并发场景下的累加。// AtomicInteger vs LongAdder// 低并发两者差不多// 高并发LongAdder 性能更好6. 实战示例计数器publicclassPageViewCounter{privateAtomicIntegercountnewAtomicInteger(0);publicvoidaddView(){count.incrementAndGet();}publicintgetViews(){returncount.get();}}防止重复提交publicclassSubmitService{privateAtomicBooleansubmittingnewAtomicBoolean(false);publicvoidsubmit(){// 如果已经在提交中直接返回if(!submitting.compareAndSet(false,true)){return;}try{// 业务逻辑doSubmit();}finally{submitting.set(false);}}}配置更新publicclassConfigHolder{privateAtomicReferenceConfigconfigRefnewAtomicReference();publicvoidupdateConfig(ConfignewConfig){configRef.updateAndGet(old-newConfig);}publicConfiggetConfig(){returnconfigRef.get();}}7. 总结类用途AtomicInteger整数原子操作AtomicLong长整数原子操作AtomicBoolean布尔原子操作AtomicReference对象引用原子操作AtomicIntegerArray整数数组原子操作LongAdder高并发累加比 AtomicLong 性能更好什么时候用需要保证多线程安全地修改一个值时简单计数、状态标记等场景比 synchronized 性能更好