

32位系统下,Go标准库中atomic原子操作int64有崩溃bug
source link: https://www.pengrl.com/p/21030/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

32位系统下,Go标准库中atomic原子操作int64有崩溃bug
下面这个demo,在32位系统(我测试的运行环境:32位arm linux)会崩溃。
package main
import (
"sync/atomic"
)
type Foo struct {
a int64
b int32
c int64
}
func main() {
var f Foo
atomic.AddInt64(&f.a, 1) // 这里不会崩溃
atomic.AddInt64(&f.c, 1) // 这里会崩溃
}
崩溃信息如下:
panic: unaligned 64-bit atomic operation
goroutine 1 [running]:
runtime/internal/atomic.panicUnaligned()
/usr/local/go/src/runtime/internal/atomic/unaligned.go:8 +0x24
runtime/internal/atomic.Xadd64(0x1416084, 0x1, 0x0, 0x75fd8, 0x14000e0)
/usr/local/go/src/runtime/internal/atomic/asm_arm.s:233 +0x14
main.main()
/tmp/test.go:16 +0x3c
在Go源码go/src/sync/atomic/doc.go
的注释中,有如下描述:
// BUG(rsc): On x86-32, the 64-bit functions use instructions unavailable before the Pentium MMX.
//
// On non-Linux ARM, the 64-bit functions use instructions unavailable before the ARMv6k core.
//
// On ARM, x86-32, and 32-bit MIPS,
// it is the caller's responsibility to arrange for 64-bit
// alignment of 64-bit words accessed atomically. The first word in a
// variable or in an allocated struct, array, or slice can be relied upon to be
// 64-bit aligned.
大致意思是,在一些32位的环境(包括x86和arm),标准库sync/atomic
中操作int64的函数存在bug,调用者需自行保证,被操作的int64是按64位对齐的。。否则给你来个panic。惊不惊喜意不意外。。
这里简单说一下64位对齐是啥意思,拿上面那个demo来说:
type Foo struct {
a int64 // 位置从0开始,满足64位对齐
b int32
c int64 // 位置`size(a)+sizeof(b)=96`,不是64的倍数,就不满足了
}
所以,atomic.AddInt64(&f.a, 1)
不会崩溃,atomic.AddInt64(&f.c, 1)
会崩溃。
值得一提的有几点:
- 64位系统原子操作int64没这个问题
- 32位系统原子操作int32也没问题
- 32位系统原子操作int64有问题,注意,是原子操作有问题,并不是说int64不能用
- uint64和int64是一样,也即这个问题只关心整型位数,不关心符号
- 以上说的原子操作,特指Go标准库
sync/atomic
中的函数
解决方法有两种:
一种是保证结构体中的需要使用atomic的int64按64位对齐,比如最简单的就是把这些变量的声明写在结构体的最前面。同时,还需要保证这种结构体被其他结构体嵌套时,也要64位对齐。缺点是编写和维护代码的心智负担比较大。
另一种就是把int64变量的原子操作改成mutex互斥锁保护。缺点是mutex比atomic的开销大。
我自己的更佳方案:
在我自己的Go基础库naza(https://github.com/q191201771/naza)中,增加对64位原子整型的封装,让它按运行系统的类型(32/64)做条件编译,64位系统内部使用Go标准库atomic中的原子操作函数实现,32位则内部退化成使用mutex实现。
本文完,作者yoko,尊重劳动人民成果,转载请注明原文出处: https://pengrl.com/p/21030/
Recommend
-
43
1.SortedList顾名思义就是排序列表,它适用于列表有序且不重复的场景。并且SortedList会帮助你比较数据的差异,定向刷新数据。而不是简单粗暴的notifyDataSetChanged()。我想到了一个场景,在选择城市页面,我们都需要根据拼音首字母来排序。我们来使用SortedList...
-
50
背景 有这样一个需求,一位 React Suite(以下简称 rsuite)的用户,他需要一个 Table 组件能够像 Jira Portfolio 一样,支持树形数据,同时需要支持大数据渲染。 截止到目前(2019年1月17日)为止,开源 UI 库中没有找到
-
47
-
49
啰嗦几句 我本来想说的是Unix系统C标准库所提供的一些算法和数据结构API,但毕竟带有iOS标题可能更加吸引眼球一些。其实我说的也没有错,因为iOS毕竟是从Unix衍生出来的系统,所以说标题所述也算是正确的。下面将要介绍的几类API...
-
77
作者: 喵叔 原文: b...
-
36
点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点个在看或点个赞,感谢~ 公众号—— Pou光明 场景引入: 在一个尚未成...
-
6
c++标准库:并发(五) —— 原子变量 std::atomic与内存序 作者: 邹成卓 2021-06-14 19:58:03 分类:
-
4
Go标准库
-
4
原子操作和atomic关键字 | 沉默杀手原子操作和atomic关键字 2022-05-18|
-
18
Python进阶(17)—使用标准库中的模块◎知识点模块的概述使用标准库中的模块导入模块的方式
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK