按照go的说明,goroutine的调度方式为先运行最后一个goroutinue,剩下的按照顺序依次运行。 若无系统调用则不发生调度 若无非内敛函数调用,则不发生抢占式调度(go 1.4) 可是以下代码的结果不太明白 // main
func main() {
data := make([]byte, 256)
for i := 0; i < 256; i++ {
data[i] = byte(i)
}
runtime.GOMAXPROCS(1)
exitChan := make(chan int, 10)
t0 := time.Now().UnixNano()
for i := 0; i < 10; i++ {
go func(j int) {
ret := uint64(0)
for x := uint64(0); x < uint64(j*40000000); x++ {
ret = uint64(utils.MurmurHash2(data, uint32(ret)))
}
exitChan <- j
}(i)
}
for i := 0; i < 10; i++ {
fmt.Print(<-exitChan, time.Now().UnixNano()-t0, "\n")
}
} // Mixing constants; generated offline. const ( M = 0x5bd1e995 BIGM = 0xc6a4a7935bd1e995 R = 24 BIGR = 47 )
// 32-bit mixing function. func mix2(h uint32, k uint32) (uint32, uint32) { k = M k ^= k >> R k = M h *= M h ^= k return h, k }
// The original MurmurHash2 32-bit algorithm by Austin Appleby. func MurmurHash2(data []byte, seed uint32) (h uint32) { var k uint32
// Initialize the hash to a 'random' value
h = seed ^ uint32(len(data))
// Mix 4 bytes at a time into the hash
for l := len(data); l >= 4; l -= 4 {
k = uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16 | uint32(data[3])<<24
h, k = mix2(h, k)
data = data[4:]
}
// Handle the last few bytes of the input array
switch len(data) {
case 3:
h ^= uint32(data[2]) << 16
fallthrough
case 2:
h ^= uint32(data[1]) << 8
fallthrough
case 1:
h ^= uint32(data[0])
h *= M
}
// Do a few final mixes of the hash to ensure the last few bytes are well incorporated
h ^= h >> 13
h *= M
h ^= h >> 15
return
}
有疑问加站长微信联系(非本文作者)

根据假设,j=9的routine先运行,若不发生抢占式调度,接着依次是012345678,最后的打印结果是9012345678 如果发生调度,那么根据时间来看,0是最先打印的,接着是123456789,因为hash操作比较费时间。 但是实际结果很奇怪。当循环的常数比较大时,结果是091234567.好像是抢占式调度了 当常数较小时,是9012345678,应该是没有抢占 当常数在某个范围内时,打印的结果是乱序的
go的说明原文能贴出来吗?想看看。
记不清了 大致是这样的
我也记得在哪看过这个说法,但是不是原文,是某篇博客。想找原文呼应一下。
关于goroutine的执行顺序官方文档肯定不会说谁先谁后,只会告诉你不要假设他们谁先谁后,因为并发就是这样规定的。不知道你假定goroutine的执行顺序有何意义?当然按照目前的runtime实现,指定一个P,创建少量的goroutine,是会先运行最后一个goroutinue,剩下的按照顺序依次运行。因为P的结构中有runnext字段用来保存最后新建的goroutine,M去找G来运行的时候也是优先找p的runnext。 但是这仅仅goroutine的没被抢占,M还未执行P本地队列中的G。如果你试试创建大量的G,就会发现goroutine的执行顺序并不符合你的说明。 详细的实现需要看runtime的具体代码,有兴趣可以一起阅读 https://github.com/sheepbao/golang_runtime_reading, 里面有我注释的golang 调度实现,可以回答你的问题。
https://github.com/sheepbao/golang_runtime_reading 前面的链接会报错
嗯,我是想学习一下内部调度原理,代码层面不会依赖这个顺序,