Skip to content

Instantly share code, notes, and snippets.

@x893675
Created September 9, 2020 01:39
Show Gist options
  • Save x893675/05d088aaaa4f4d9e8f132b077af73b2a to your computer and use it in GitHub Desktop.
Save x893675/05d088aaaa4f4d9e8f132b077af73b2a to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
testA()
//testB()
//testC()
}
// 由于闭包只是绑定到这个value变量上,并没有被保存到goroutine栈中,
// 所以以上代码极有可能运行的结构都输出为切片的最后一个元素。
// 因为这样写会导致for循环结束后才执行goroutine多线程操作,这时候value值只指向了最后一个元素。
func testA() {
var wg sync.WaitGroup
for i := 1; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(i)
}()
}
wg.Wait()
}
// 乱序打印
func testB() {
var wg sync.WaitGroup
for i := 1; i < 10; i++ {
wg.Add(1)
go func(value int) {
defer wg.Done()
fmt.Println(value)
}(i)
}
wg.Wait()
}
// 固定输出 9,1,2,3,4,5,6,7,8
// runtime2.go 中关于 p 的定义: 其中 runnext 指针决定了下一个要运行的 g,根据英文的注释大致意思是说:
//
// 1 . 如果 runnext 不为空且是就绪的,那么应该优先运行该 runnext 指向的 g 而不是运行队列中到达运行时间的 g。
// 2 . 此时要被运行的 g 将继承当前 g 剩余的时间片继续执行。
// 3 . 之所以这样做是为了消除将最后的 g 添加到队列末尾导致的潜在的调度延迟。
// 所以当设置 runtime.GOMAXPROCS(1) 时,此时只有一个 P,创建的 g 依次加入 P, 当最后一个即 i==9 时,
// 加入的最后 一个 g 将会继承当前主 goroutinue 的剩余时间片继续执行,所以会先输出 9, 之后再依次执行 P 队列中其它的 g。
func testC() {
runtime.GOMAXPROCS(1)
var wg sync.WaitGroup
for i := 1; i < 10; i++ {
wg.Add(1)
go func(value int) {
defer wg.Done()
fmt.Println(value)
}(i)
}
wg.Wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment