package main import ( "fmt" "sync" "sync/atomic" "time" ) // =============== ABA 问题演示(增强时序稳定性) =============== func demoABAProblem() { var value int32 = 100 var wg sync.WaitGroup ready := make(chan struct{}) // 同步信号:确保 A 先读取 wg.Add(2) // Goroutine A: 读取初始值后等待信号 go func() { defer wg.Done() old := atomic.LoadInt32(&value) // 读取到 100 <-ready // 等待 B 完成 ABA 修改 if atomic.CompareAndSwapInt32(&value, old, 200) { fmt.Println("⚠️ ABA 问题触发: CAS 成功!但值曾被篡改 (100→150→100)") } else { fmt.Println("❌ 未复现 ABA(调度异常)") } }() // Goroutine B: 执行 A→B→A 修改 go func() { defer wg.Done() time.Sleep(5 * time.Millisecond) // 确保 A 已读取 atomic.StoreInt32(&value, 150) // A→B atomic.StoreInt32(&value, 100) // B→A close(ready) // 通知 A 执行 CAS }() wg.Wait() fmt.Printf("最终值: %d (ABA 发生时应为 200)\n", value) } // =============== 安全方案:位域编码防 ABA =============== // 64位结构: [高32位: 版本号] | [低32位: 实际值] type VersionedInt32 struct { data int64 // 原子存储单元 } // 合并值与版本号 func pack(val, ver int32) int64 { return (int64(ver) << 32) | int64(uint32(val)) } // 拆解:返回 (值, 版本号) func unpack(data int64) (val int32, ver int32) { return int32(data), int32(data >> 32) // 低32位=值, 高32位=版本 } // 安全读取当前值 func (v *VersionedInt32) Load() int32 { val, _ := unpack(atomic.LoadInt64(&v.data)) // 取第一个返回值 return val } // 带版本号的原子 CAS(彻底规避 ABA) func (v *VersionedInt32) CAS(oldVal, newVal int32) bool { for { current := atomic.LoadInt64(&v.data) curVal, curVer := unpack(current) if curVal != oldVal { return false // 值已变更,拒绝更新 } // 构造新状态:值更新 + 版本号+1 newState := pack(newVal, curVer+1) if atomic.CompareAndSwapInt64(&v.data, current, newState) { return true } // 失败则重试 } } func main() { fmt.Println("=== ABA 问题演示(通道同步确保时序) ===") demoABAProblem() fmt.Println("\n=== 安全方案验证(位域编码) ===") vv := &VersionedInt32{data: pack(100, 0)} // 初始值=100, 版本=0 // 首次 CAS:100 → 200 if vv.CAS(100, 200) { val := vv.Load() _, ver := unpack(atomic.LoadInt64(&vv.data)) fmt.Printf("✅ CAS 成功 | 值: %d, 版本: %d\n", val, ver) } // 尝试用过期旧值 100 更新(应失败) if !vv.CAS(100, 300) { fmt.Println("✅ 检测到非法修改:CAS 拒绝使用过期旧值更新") } // 使用当前正确值更新 if vv.CAS(200, 300) { fmt.Printf("✅ 安全更新成功 | 当前值: %d\n", vv.Load()) } }