求教 Go 里 goroutine 去通道里拿数据 必定后来的先拿走吗?

2017-11-30 15:51:40 +08:00
 dushandz
package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var wg sync.WaitGroup

func init() {
	rand.Seed(time.Now().UnixNano())
}
func main() {
	court := make(chan int)
	wg.Add(2)
	go player("A", court)
	go player("B", court)
	court <- 1
	wg.Wait()
}

func player(name string, court chan int) {
	defer wg.Done()
	for {
		ball, ok := <-court //走到这里就会阻塞 是吧?
		if !ok {            //通道关闭
			fmt.Printf("Player %s Won\n", name)
			return
		}
		n := rand.Intn(100)
		if n%13 == 0 {
			fmt.Printf("Player %s missed\n", name)
			close(court)
			return
		}
		fmt.Printf("Player %s Hit %d \n", name, ball)
		ball++
		court <- ball

	}
}

每次打印都是 B 所在的协程先触发

1374 次点击
所在节点    Go 编程语言
7 条回复
araraloren
2017-11-30 16:09:04 +08:00
Please search `程序的局部性原理`
dushandz
2017-11-30 16:16:58 +08:00
@araraloren ?? 我间隔一段时间 或者 每次跑之前都 clean 还是这样啊
Micky
2017-11-30 16:53:01 +08:00
增加一个协程:
wg.Add(3)
go player("A", court)
go player("B", court)
go player("C", court)
执行几次你会发现,有时候是 CBA 的顺序,有时候是 CAB 的顺序
确实每次都是 C 最先激活,但 B 和 A 的顺序却是随机的
因此可以推断:并没有固定的 FIFO 或 LIFO 的顺序,但 runtime 在第一次挑选的时候具有某种倾向性
Micky
2017-11-30 16:56:23 +08:00
@Micky #3 这个倾向性可能就是 1 楼所说的局部性原理体现吧,不要当做固定特性去 rely on 就行了
cholerae
2017-11-30 17:23:01 +08:00
纯粹跟 runtime 实现有关,语言上没有做任何保证,不要依赖这个行为。
per
2017-11-30 17:53:02 +08:00
dushandz
2017-12-01 10:17:23 +08:00
@Micky @per @cholerae @araraloren 多谢大佬们

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/410853

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX