sync.waitGroup
GO版本1.14
Gosync.waitGroup
WaitGroupstate1长度为3的uint32类型的数组statewaiter数量sema信号量if
ifuintptr(unsafe.Pointer(&wg.state1))%8 == 0wg.state180
wg.state1wg.state1[0]wg.state1[2]wg.state1[1]wg.state1[0]
为什么是对8取模?
wg.state188
在不同的硬件平台上,内存以字节为单位,不一定支持任何内存地址的存取,一般可能以双字节、4字节等为单位存取内存,为了保证处理器正确存取数据,需要进行内存对齐。 这样做的好处是能够提高CPU内存访问速度,一般处理器的内存存取粒度都是N的整数倍,假如访问N大小的数据,没有进行内存对齐,有可能就需要两次访问才可以读取出数据,而进行内存对齐可以一次性把数据全部读取出来,提高效率。
if4(32/8)8(64/8)if8wg.state1864位32位
wg.state1waitGroup.state1
从图中,我们可以清晰的看出,在不同平台下,数据元素表示的含义发生了变化,现在我们可以观察下面的源码(删除了冗余的部分):
wg.state()statepstatepwg.state1
为什么平台不同,元素的含义也不同?
wg.statestatep64位的原子操作64位的原子操作64位对齐8
32位对齐wg.state164位平台wg.state1[0]32位对齐64位对齐wg.state10xc420016244 wg.state1
waiter数量wg.state1[0]wg.state1[0]wg.state1[1]atomic.AddUnit64
Go如何处理内存对齐?
Go
Go
struct:T1 和 T2
=== RUN TestPointerAlignment
T1 sizeof = 24; alignof = 8
T2 sizeof = 16; alignof = 8
--- PASS: TestPointerAlignment (0.00s)
PASS
复制代码
Gounsafe.Alignofstruct2416[2]int8、int64、int16
struct结构填充
结构如何填充?
我们以64位机器的填充过程为例,如下图所示:
strutct T1和T2
综上,我们可以知道编译器,按照字段声明的顺便读取字段,并按块(跟机器相关:64bit-8B;32bit-4B)读取数据,在遇到不满块大小的字段时,会自动进行结构填充,使用充满块大小,这样是为了提高CPU读区内存的效率,避免过多的数据拼接和过滤。
下面我们再来看一种特殊情况。
struct
我们还是用一个demo来说明:
=== RUN TestZeroSizedFieldAlignment
T3.E Offsetof = 32, T3.E Sizeof = 0, T3 Sizeof = 40
--- PASS: TestZeroSizedFieldAlignment (0.00s)
PASS
复制代码
T3.Estructsturct8
T3.E
=== RUN TestEmptyFieldPointer
T3 Sizeof = 32; T3.E Sizeof = 0
--- PASS: TestEmptyFieldPointer (0.00s)
PASS
复制代码
T3
T3.E
=== RUN TestZeroSizedFieldAlignment
T4.E Offsetof = 32, T4.E Sizeof = 0, T4 Sizeof = 40
--- PASS: TestZeroSizedFieldAlignment (0.00s)
PASS
复制代码
Gostructstruct
零大小字段(zero sized field)是指struct{},大小为 0,按理作为字段时不需要对齐,但当在作为结构体最后一个字段(final field)时需要对齐的。即开篇我们讲到的面试题的情况,假设有指针指向这个final zero field, 返回的地址将在结构体之外(即指向了别的内存),如果此指针一直存活不释放对应的内存,就会有内存泄露的问题(该内存不因结构体释放而释放),go 会对这种final zero field也做填充,使对齐。当然,有一种情况不需要对这个final zero field做额外填充,也就是这个末尾的上一个字段未对齐,需要对这个字段进行填充时,final zero field就不需要再次填充,而是直接利用了上一个字段的填充。
Go
=== RUN TestTypeAlignmentGuarantee
T8.B Sizeof = 12, T8.B Alignment = 4, T8 Sizeof = 12, T8 Alignment = 4
--- PASS: TestTypeAlignmentGuarantee (0.00s)
PASS
复制代码
struct
type alignment guarantee
------ ------
bool, uint8, int8 1
uint16, int16 2
uint32, int32 4
float32, complex64 4
arrays 元素的内存对齐保证
structs 字段中最大的内存对齐保证
other types 机器字长
复制代码
sync.waitGroup
最后,感谢阅读。