2 回答

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超5個(gè)贊
在第一種情況下,錯(cuò)誤是由原子更新的字段沒(méi)有正確對(duì)齊引起的。
在 ARM 和 x86-32 上,調(diào)用者負(fù)責(zé)安排以原子方式訪問(wèn)的 64 位字的 64 位對(duì)齊。全局變量或分配的結(jié)構(gòu)體或切片中的第一個(gè)字可以依賴于 64 位對(duì)齊。

TA貢獻(xiàn)1775條經(jīng)驗(yàn) 獲得超11個(gè)贊
如果您偶然發(fā)現(xiàn)此錯(cuò)誤,這里有一些解決問(wèn)題的技巧:
如 OP 中所述,最簡(jiǎn)單的方法是將所有 64 位原子值放在結(jié)構(gòu)的頂部:
c := struct {
val int64 // pos 0
val2 int64 // pos 8
valid bool // pos 16
}{val2: 1}
fmt.Println(atomic.AddInt64(&c.val2, 1))
如果您出于某種原因不想將此字段放在頂部,則始終可以_ [4]byte在 64 位字段上方放置 a以確保正確填充它。
c := struct {
val int64 // pos 0
valid bool // pos 8
_ [4]byte // pos 9; compiler adds additional [3]byte at pos 13 for alignment
val2 int64 // pos 16, correctly aligned
}{val2: 1}
fmt.Println(atomic.AddInt64(&c.val2, 1)) // => 2
請(qǐng)注意,如果字段已經(jīng)對(duì)齊,這將不起作用;相反,如果它之前沒(méi)有恐慌,它現(xiàn)在就會(huì)恐慌。
c := struct {
val int64 // pos 0
_ [4]byte // pos 8; compiler adds no padding
val2 int64 // pos 12, not a multiple of 8!
}{val2: 1}
fmt.Println(atomic.AddInt64(&c.val2, 1)) // => runtime error: invalid memory address [...]
您還可以依賴 64 位元素切片中的第一個(gè)元素將正確對(duì)齊的行為:
c := struct {
val int64
valid bool
val2 []int64
}{val2: []int64{1}}
fmt.Println(atomic.AddInt64(&c.val2[0], 1))
請(qǐng)注意,這不適用于數(shù)組,因?yàn)樗鼈兊闹抵苯哟鎯?chǔ)在結(jié)構(gòu)中,而不是像切片數(shù)據(jù)那樣存儲(chǔ)在堆中。
您可以使用的最后一個(gè)技巧是將結(jié)構(gòu)中的字段聲明為指向int64;的指針。如果int64它指向的是對(duì)齊的,那么它會(huì)順利運(yùn)行。
c := struct {
val int64
valid bool
val2 *int64
}{val2: new(int64)}
fmt.Println(atomic.AddInt64(c.val2, 1))
如果你不想弄臟你的手sync/atomic,請(qǐng)記住,這sync.Mutex是一個(gè)比處理原子更清晰、更容易理解的解決方案。
- 2 回答
- 0 關(guān)注
- 348 瀏覽
添加回答
舉報(bào)