阅读 runqput 源码的几个疑问

来源:1-4 Go 程序是怎么跑起来的

EwdAger

2021-05-19 17:51:36

func runqput(_p_ *p, gp *g, next bool) {
	if randomizeScheduler && next && fastrand()%2 == 0 {
		next = false
	}

	if next {
	retryNext:
		oldnext := _p_.runnext
		if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))) {
			goto retryNext
		}
		if oldnext == 0 {
			return
		}
		// Kick the old runnext out to the regular run queue.
		gp = oldnext.ptr()
	}

问题一

上述代码中 if randomizeScheduler && next && fastrand()%2 == 0 这个判断是不是只是为了关闭调度中的 runnext 机制?具体什么情况下会用到这种机制呢?

问题二

if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))),我的理解应该是用新加入的gp替换oldnext,如果失败了就重试,那么什么情况会失败呢?还是说这只是一个代码规范性问题?

问题三

if oldnext == 0 是因为gp加入进来之前,runnext里是空的,所以把 gp塞入runnext就不管了,直接 return。不知道我的理解对不对

写回答

1回答

助教_小R

2021-07-24

问题一:


这个是和 race 相关的,一般我们看源码的时候,碰到 race 直接跳过,不用深究。


问题二:


这个 cas 的意思是将 _p_.runnext 与 oldnext 比较,如果相等,再替换,是一个原子操作。主是是其他地方也有 goroutine 相往这个 P 上塞。


http://img.mukewang.com/climg/60fbc27209b9e43b16100538.jpg


问题三:


对的。

1

Go高级工程师实战营

慕课网与 GoCN 社区官方联手打造,定义行业Go高级人才培养标准,4个月,快速晋升为P6+/D7级高级人才。

458 学习 · 266 问题

查看课程