求求爹给解答下 golang sync.WaitGroup 的疑惑

11次阅读

共计 1233 个字符,预计需要花费 4 分钟才能阅读完成。

实在看不懂了,越看越懵,sync.Mutex 无压力看懂,到这个 waitgroup 就跪了,求亲爹指教一下,跪谢

首先 waitgroup 基本每个版本都有改动,每个改动都逃不开几个话题,内存对齐、原子性

先看一下 1.17 的结构

type WaitGroup struct {
	noCopy noCopy
	state1 [3]uint32
}

func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2]
	} else {return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0]
	}
}

再看一下 1.18 的结构

type WaitGroup struct {
	noCopy noCopy
	state1 uint64
	state2 uint32
}

func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {if unsafe.Alignof(wg.state1) == 8 || uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
		// state1 is 64-bit aligned: nothing to do.
		return &wg.state1, &wg.state2
	} else {
		// state1 is 32-bit aligned but not 64-bit aligned: this means that
		// (&state1)+4 is 64-bit aligned.
		state := (*[3]uint32)(unsafe.Pointer(&wg.state1))
		return (*uint64)(unsafe.Pointer(&state[1])), &state[0]
	}
}

在 32 位系统下,state 函数会走 else,让 state1[1] 和 state1[2] 一起变成 uint64,这个 uint64 大小为 8 字节 64 位

waitgroup 废了这么大劲,网上说主要是为了对齐和原子性

1. 我不理解如何保证原子性
使用 state1 字段时候,都用了 atmoic,我理解 atmoic 已经保证了原子性,莫非是 32 位系统读取 64 位 uint64 时候,这个读操作不是原子性的??如果是这样那么我不理解问题 2

2. 为什么 state 函数在 32 位上的实现可以保证原子性
假如 uint64 占用了 0~31 和 32~63 两个地址位,那么无论怎么对齐,32 位系统怎么能保证一次性、原子性的把这 64 位地址读出来?

3. 为什么 state 函数对 8 取模就能判断是 64 位还是 32 位系统
32 位系统中 WaitGroup 结构体就不能是地址 0x00008 么??这样对 8 取模会判断成是 64 位

4. 为啥不直接使用 uint32,解决了对齐和原子性问题

虚心求教

正文完
 0