news 2026/4/17 20:24:49

原子操作:并发编程的基石

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
原子操作:并发编程的基石

原子操作:并发编程的基石

原子操作是并发编程中最核心的概念之一,理解它对于编写正确、高效的多线程程序至关重要。

🔬 原子操作的定义

原子操作(Atomic Operation)指的是不可被中断的一个或一系列操作,这些操作要么全部执行成功,要么全部不执行,不存在中间状态。原子操作在多线程环境下是线程安全的,因为其他线程无法看到原子操作的中间状态。

关键特征:

  1. 不可分割(Indivisible):操作作为一个整体执行
  2. 不可中断(Non-interruptible):执行过程中不会被线程调度打断
  3. 一致性视图(Consistent View):其他线程看到的是操作前或操作后的状态,不会看到中间状态

💡 直观理解

想象一个银行转账操作:

// ❌ 非原子操作:分两步执行,可能被中断account.balance=account.balance-100;// 步骤1:扣款recipient.balance=recipient.balance+100;// 步骤2:存款// 如果在步骤1和步骤2之间发生线程切换:// 线程A:执行步骤1(扣款成功)// [线程切换发生]// 线程B:读取account.balance(看到扣款后的余额,但收款方还没收到钱)// 线程B:执行其他操作...(数据不一致!)// ✅ 原子操作:要么全成功,要么全失败atomicTransfer(account,recipient,100);

🏗️ 硬件层面的原子操作

1.CPU指令级的原子操作

现代CPU提供了一些原子指令:

; x86架构的原子指令示例 LOCK XADD ; 原子加 LOCK CMPXCHG ; 比较并交换(CAS) LOCK INC ; 原子自增 LOCK DEC ; 原子自减 ; 这些指令前缀LOCK会锁定内存总线,确保操作原子性

2.CAS(Compare and Swap)原理

CAS是大多数原子操作的基础:

// CAS操作的伪代码publicclassCAS{// 内存位置V,期望值A,新值BbooleancompareAndSwap(int*V,intA,intB){if(*V==A){// 如果内存值等于期望值*V=B;// 更新为新值returntrue;// 成功}returnfalse;// 失败}}// 实际使用volatileintvalue=0;// 原子地更新value:如果当前是0,则改为1while(true){intcurrent=value;intnext=current+1;if(compareAndSwap(&value,current,next)){break;// 更新成功}// 更新失败(被其他线程修改),重试}

3.内存屏障(Memory Barrier)

确保指令执行顺序和内存可见性:

// Java中的内存屏障publicclassMemoryBarrierExample{privatevolatileintflag=0;privateintdata=0;publicvoidwrite(){data=42;// 普通写// StoreStore屏障(volatile写之前)flag=1;// volatile写,包含内存屏障// StoreLoad屏障(volatile写之后)}publicvoidread(){if(flag==1){// volatile读,包含内存屏障// LoadLoad屏障(volatile读之后)// LoadStore屏障(volatile读之后)System.out.println(data);// 保证看到data=42}}}

📚 原子操作的类型

1.基本原子操作

importjava.util.concurrent.atomic.*;// 1. 原子整型AtomicIntegeratomicInt=newAtomicInteger(0);atomicInt.incrementAndGet();// i++ 原子版本atomicInt.getAndAdd(5);// 先获取再加atomicInt.compareAndSet(0,1);// CAS操作// 2. 原子长整型AtomicLongatomicLong=newAtomicLong(0L);// 3. 原子布尔型AtomicBooleanatomicBool=newAtomicBoolean(false);// 4. 原子引用AtomicReference<String>atomicRef=newAtomicReference<>("initial");atomicRef.compareAndSet("initial","updated");// 5. 原子数组AtomicIntegerArrayatomicArray=newAtomicIntegerArray(10);atomicArray.getAndAdd(0,5);// 原子更新数组元素

2.复合原子操作

// 原子更新器publicclassBankAccount{privatevolatileintbalance;// 自定义原子操作:安全转账publicbooleantransfer(BankAccountto,intamount){while(true){intfromBalance=this.balance;if(fromBalance<amount){returnfalse;// 余额不足}inttoBalance=to.balance;// CAS更新:同时修改两个账户if(AtomicInteger.compareAndSet(this.balance,fromBalance,fromBalance-amount)&&AtomicInteger.compareAndSet(to.balance,toBalance,toBalance+amount)){returntrue;// 转账成功}// 失败重试}}}// 原子字段更新器(无需volatile,性能更好)classCounter{privateintcount;privatestaticfinalAtomicIntegerFieldUpdater<Counter>updater=AtomicIntegerFieldUpdater.newUpdater(Counter.class,"count");publicvoidincrement(){updater.incrementAndGet(this);}}

⚡ Java中的原子操作实现

1.Unsafe类 - 底层原子操作

// Unsafe是Java中执行原子操作的底层类publicclassUnsafeExample{privatestaticfinalUnsafeUNSAFE=getUnsafe();privatestaticfinallongVALUE_OFFSET;privatevolatileintvalue;static{try{// 获取字段偏移量VALUE_OFFSET=UNSAFE.objectFieldOffset(UnsafeExample.class.getDeclaredField("value"));}catch(Exceptione){thrownewError(e);}}// 使用Unsafe实现原子操作publicbooleancompareAndSet(intexpect,intupdate){returnUNSAFE.compareAndSwapInt(this,VALUE_OFFSET,expect,update);}publicintgetAndIncrement(){while(true){intcurrent=value;intnext=current+1;if(compareAndSet(current,next)){returncurrent;}}}privatestaticUnsafegetUnsafe(){// 反射获取Unsafe实例(实际使用中不推荐)// ...}}

2.Atomic类的实现原理

// AtomicInteger源码分析publicclassAtomicIntegerextendsNumberimplementsjava.io.Serializable{privatestaticfinallongserialVersionUID=6214790243416807050L;// 1. 使用Unsafe进行原子操作privatestaticfinalUnsafeUNSAFE=Unsafe.getUnsafe();privatestaticfinallongvalueOffset;static{try{// 获取value字段的内存偏移量valueOffset=UNSAFE.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));}catch(Exceptionex){thrownewError(ex);}}// 2. volatile保证可见性privatevolatileintvalue;// 3. CAS实现publicfinalbooleancompareAndSet(intexpect,intupdate){returnUNSAFE.compareAndSwapInt(this,valueOffset,expect,update);}// 4. 自增的原子实现publicfinalintincrementAndGet(){returnUNSAFE.getAndAddInt(this,valueOffset,1)+1;}// 5. 乐观锁循环publicfinalintgetAndAdd(intdelta){returnUNSAFE.getAndAddInt(this,valueOffset,delta);}}

3.LongAdder - 高并发优化

// LongAdder:分段累加,减少竞争publicclassLongAdderExample{privatefinalLongAdderadder=newLongAdder();publicvoidhighConcurrencyIncrement(){// 在高度竞争环境下性能优于AtomicLongadder.increment();// 内部原理:多个Cell分散竞争// base + cell[0] + cell[1] + ... + cell[n]}publiclongsum(){returnadder.sum();// 返回总和}}// LongAdder vs AtomicLong性能对比// 线程数少时:AtomicLong更快// 线程数多时:LongAdder更快(减少CAS竞争)

🔄 原子操作 vs 锁

性能对比:

// 测试代码:对比不同实现的性能publicclassPerformanceTest{privateintcounter=0;privatefinalAtomicIntegeratomicCounter=newAtomicInteger(0);privatefinalReentrantLocklock=newReentrantLock();// 1. 非线程安全(最快的,但可能出错)publicvoidunsafeIncrement(){counter++;}// 2. synchronized锁(较慢)publicsynchronizedvoidsynchronizedIncrement(){counter++;}// 3. ReentrantLock(比synchronized稍快)publicvoidlockIncrement(){lock.lock();try{counter++;}finally{lock.unlock();}}// 4. 原子操作(最快且线程安全)publicvoidatomicIncrement(){atomicCounter.incrementAndGet();}// 5. LongAdder(高并发时最快)privatefinalLongAdderlongAdder=newLongAdder();publicvoidlongAdderIncrement(){longAdder.increment();}}

性能测试结果(假设):

线程数: 1 synchronized: 100 ns/op ReentrantLock: 90 ns/op AtomicInteger: 15 ns/op LongAdder: 20 ns/op 线程数: 10 synchronized: 500 ns/op ReentrantLock: 450 ns/
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 5:30:44

Halo仪表盘组件开发实战:从零开始构建你的第一个Vue组件

Halo仪表盘组件开发实战&#xff1a;从零开始构建你的第一个Vue组件 【免费下载链接】halo 强大易用的开源建站工具。 项目地址: https://gitcode.com/GitHub_Trending/ha/halo 还记得第一次看到Halo那整洁美观的仪表盘界面时的惊喜吗&#xff1f;作为一名前端开发者&am…

作者头像 李华
网站建设 2026/4/18 6:59:32

crypto-js 4.2.0 终极指南:自定义KDF哈希器完全解析

crypto-js 4.2.0 终极指南&#xff1a;自定义KDF哈希器完全解析 【免费下载链接】crypto-js 项目地址: https://gitcode.com/gh_mirrors/cry/crypto-js 你是否在为密钥派生算法固定而困扰&#xff1f;crypto-js 4.2.0版本带来的自定义KDF哈希器功能&#xff0c;彻底改变…

作者头像 李华
网站建设 2026/4/18 5:32:51

JAVA赋能摄影约拍:线上预约,让美好瞬间不再错过

JAVA赋能摄影约拍&#xff1a;线上预约&#xff0c;让美好瞬间不再错过在生活节奏日益加快的当下&#xff0c;人们愈发珍视那些稍纵即逝的美好瞬间&#xff0c;渴望用摄影将其定格。然而&#xff0c;传统摄影约拍方式常因信息不对称、沟通不畅、预约流程繁琐等问题&#xff0c;…

作者头像 李华
网站建设 2026/4/18 7:00:56

Vue虚拟滚动列表实战:突破大数据渲染的性能瓶颈

在现代Web应用中&#xff0c;处理大规模数据列表是一个常见的挑战。当列表项数量达到数千甚至数万时&#xff0c;传统的DOM渲染方式会导致页面卡顿、内存占用飙升&#xff0c;严重影响用户体验。vue-virtual-scroll-list正是为解决这一痛点而生的高性能虚拟滚动组件&#xff0c…

作者头像 李华
网站建设 2026/4/18 5:30:50

5分钟快速上手CLIP-ReID图像重识别:零基础实战指南

5分钟快速上手CLIP-ReID图像重识别&#xff1a;零基础实战指南 【免费下载链接】CLIP-ReID Official implementation for "CLIP-ReID: Exploiting Vision-Language Model for Image Re-identification without Concrete Text Labels" (AAAI 2023) 项目地址: https:…

作者头像 李华
网站建设 2026/4/18 5:31:56

由于我不停面试Web前端,然后猛地发现...

面了大半年web前端&#xff0c;愈发意识到&#xff1a;25年想面试出彩&#xff0c;死记硬背早不管用了。能拿offer的人&#xff0c;回答都有条理&#xff0c;有细节&#xff0c;自带解决问题的底气。而多数人栽跟头&#xff0c;全绕不开这4个短板↓ 1. JS基础不扎实&#xff1…

作者头像 李华