小天管理 发表于 2024年9月5日 发表于 2024年9月5日 go memory model 中说: ...each read of a single-word-sized or sub-word-sized memory location must observe a value actually written to that location (perhaps by a concurrent executing goroutine) and not yet overwritten. 这句话是否可以理解为读一个字长以下的数据, 总是会读到某一次写入的数据, 而不会读到某个中间状态? 如果上述理解是正确的, 那么对于下面的程序: package main import ( "fmt" "sync" "time" ) type A struct { data string } func main() { a := &A{data: "b"} go func() { for { if a.data == "a" { a = &A{data: "b"} } else { a = &A{data: "a"} } } }() var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func() { for i := 0; i < 100000; i++ { // 复制 a 的指针, aa 在接下来的使用中应该指向同一个 A aa := a if aa.data != "a" && aa.data != "b" { panic(aa.data) } } wg.Done() }() } start := time.Now() wg.Wait() fmt.Println(time.Since(start)) } 由于指针 *A 是一个字长, 那么读取变量 a 总是会读到某一个 A 地址, 所以 panic 不会发生, 但实际上会出现: panic: goroutine 6 [running]: main.main.func2() /Users/a/test/test.go:44 +0xa0 created by main.main in goroutine 1 /Users/a/test/test.go:40 +0x44 exit status 2 这是为什么?
已推荐帖子