按照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,应该是没有抢占
当常数在某个范围内时,打印的结果是乱序的
#1