先说结论:257
个!
首先介绍下时间片
一个p最多持续运行10ms
,就要执行下一次调度(由go监控线程执行)。
相关代码段
路径:/go/src/runtime/proc.go
// 10ms
const forcePreemptNS = 10 * 1000 * 1000
路径:/go/src/runtime/proc.go line:5503
当p的上次调度时间+10ms <= 当前时间,说明这个g运行太久了,该换换了。
if pd.schedwhen+forcePreemptNS <= now {
preemptone(_p_) // 执行goroutine抢占
// In case of syscall, preemptone() doesn't
// work, because there is no M wired to P.
sysretake = true
}
再看P在golang中的声明
p中runq字段是一个数组存放着多个goroutine,,可存放256个。
p中runnext字段可以存放一个goroutine。
runnext字段的大致作用,一个P如果还有剩余时间片,那么P中next字段中的goroutine会继承这部分剩余时间并执行。
路径:go/src/runtime/runtime2.go line:604
type p struct {
...忽略部分...
runq [256]guintptr
// runnext, if non-nil, is a runnable G that was ready'd by
// the current G and should be run next instead of what's in
// runq if there's time remaining in the running G's time
// slice. It will inherit the time left in the current time
// slice. If a set of goroutines is locked in a
// communicate-and-wait pattern, this schedules that set as a
// unit and eliminates the (potentially large) scheduling
// latency that otherwise arises from adding the ready'd
// goroutines to the end of the run queue.
//
// Note that while other P's may atomically CAS this to zero,
// only the owner P can CAS it to a valid G.
runnext guintptr
“幼麟yysd”
网友评论