阅读 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回答
问题一:
这个是和 race 相关的,一般我们看源码的时候,碰到 race 直接跳过,不用深究。
问题二:
这个 cas 的意思是将 _p_.runnext 与 oldnext 比较,如果相等,再替换,是一个原子操作。主是是其他地方也有 goroutine 相往这个 P 上塞。
问题三:
对的。
相似问题