首次提交:初始化项目代码
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
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())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user