2026/2/15 22:50:10
网站建设
项目流程
网站图片设置4:3,网站素材下载,网页游戏单机,网上推广产品哪个网好核心问题#xff1a;count 不是原子操作
count 看起来是一行代码#xff0c;但实际对应3个CPU指令#xff1a;
// Java代码
count;// 实际执行的CPU指令#xff1a;
1. 读取count的当前值到CPU寄存器 (read)
2. 把寄存器的值加1 (add)
3. 把新值写回内存 …核心问题count 不是原子操作count看起来是一行代码但实际对应3个CPU指令// Java代码count;// 实际执行的CPU指令1.读取count的当前值到CPU寄存器(read)2.把寄存器的值加1(add)3.把新值写回内存(write)场景模拟两个线程同时执行 count假设volatile int count 0;时间线 | 线程A的操作 | 线程B的操作 | 内存中count的值 ------|--------------------------|--------------------------|---------------- 1 | read: count0 → 寄存器A0 | | 0 2 | | read: count0 → 寄存器B0 | 0 3 | add: 寄存器A011 | | 0 4 | | add: 寄存器B011 | 0 5 | write: 写回count1 | | 1 6 | | write: 写回count1 | 1应该是2结果两个线程都做了1操作但最终结果是1而不是2。volatile 在这里起了什么作用volatile只保证了当线程A在第5步写入count1时立即刷新到主内存当线程B读取时能读到最新的值如果它重新读的话但问题是线程B在第2步已经读过了读取的是0不会再重新读更详细的时序图线程A: 读count(0) → 计算1 → 写count(1,立即刷新) ↑ ↓ 内存count: 0 ← 冲突 → 1 ↑ ↓ 线程B: 读count(0) → 计算1 → 写count(1,覆盖了A的结果)volatile能解决的场景 vs 不能解决的场景✅volatile能解决的一写多读// 线程A写线程publicvoidwrite(){flagtrue;// 单个写操作data100;}// 线程B、C、D读线程publicvoidread(){if(flag){// 一定能看到trueSystem.out.println(data);// 一定能看到100}}❌volatile不能解决的多写// 线程A、B、C都执行这个publicvoidincrement(){count;// 问题在这里这个操作是读-改-写三部曲// 相当于// int temp count; // 1.读可能读到旧值// temp temp 1; // 2.改在各自线程中改// count temp; // 3.写会相互覆盖}类比解释想象一个共享的记事本内存和三个人线程场景1单写多读volatile有效只有小明可以在记事本上写小红和小刚只能看当小明更新了内容小红和小刚立刻能看到新内容 ✅场景2多写volatile无效小明、小红、小刚都可以在记事本上写当前记事本写着库存10小明看到库存10计算10-19准备写9小红同时看到库存10计算10-19准备写9小明写下9小红也写下9覆盖了小明的9结果卖了2件商品库存应该是8但实际是9 ❌为什么AtomicInteger能解决AtomicIntegercountnewAtomicInteger(0);// count.incrementAndGet() 内部原理publicfinalintincrementAndGet(){intprev,next;do{prevget();// 1.读取当前值nextprev1;// 2.计算新值}while(!compareAndSet(prev,next));// 3.比较并交换returnnext;}关键在第3步compareAndSet(prev, next)意思是“如果现在内存中的值还是我刚刚读到的prev我就把它改成next”“如果内存中的值已经被别人改了那我就重试”用记事本的例子小明看到库存10想改成9小红也看到库存10想改成9小明先写检查发现确实是10成功改成9小红再写检查发现现在是9不是10了于是重新读、重新计算9-18再写 ✅总结要点volatile只管看到最新值不管正确修改值多线程修改的核心矛盾多个线程基于同一个旧值做计算然后相互覆盖解决方案本质需要把读-改-写这三步变成一个不可分割的原子操作Atomic类用CAS比较并交换实现原子性synchronized用互斥锁实现原子性总之关键是要认识到count不是一步操作而是三步而volatile只保证了每一步内部的内存可见性但没有保证这三步作为一个整体的原子性。