golang 多个协程中 读取同一个 channel,怎么不是按顺序打印

2021-01-22 11:26:17 +08:00
 hyp1002950

func main(){

ch := make(chan int)

go func(){
	for{
		c :=<-ch
		fmt.Println("one:",c,"len:",len(ch))
	}
}()

go func(){
	for{
		c :=<-ch
		fmt.Println("two:",c,"len:",len(ch))
	}
}()

for i:=1;i<=100;i++{
	ch<-i
}

time.Sleep(time.Second * time.Duration(2))

}

5032 次点击
所在节点    Go 编程语言
31 条回复
Nitroethane
2021-01-22 17:08:12 +08:00
@hyp1002950 #11 用 sleep 并不是完美的同步方法,虽然将 sleep 的时间设置的长一点可以在很大程度上得到顺序输出,但本质上由于 goroutine 调度器的原因还是会可能出现乱序输出情况,因为哪个 goroutine 先执行取决于调度器。正确的做法是用一个无 buffer 的 channel 去做两个 goroutine 之间的同步
keepeye
2021-01-22 17:18:22 +08:00
用单核 cpu 可能得到顺序结果吧
kele1997
2021-01-22 17:52:46 +08:00
```
var lock1 sync.Mutex
var lock2 sync.Mutex

func main() {
ch := make(chan int)

lock2.Lock()
go func() {
for {
lock1.Lock()
c := <-ch
fmt.Println("one:", c, "len:", len(ch))
lock2.Unlock()
}
}()

go func() {
for {
lock2.Lock()
c := <-ch
fmt.Println("two:", c, "len:", len(ch))
lock1.Unlock()
}
}()

for i := 1; i <= 100; i++ {
ch <- i
}

time.Sleep(time.Second * time.Duration(2))
}

```
KaynW
2021-01-22 18:01:07 +08:00
@keepeye 并不会
back0893
2021-01-22 19:09:25 +08:00
协程的调用你没有办法保证是顺序调用
zhyl
2021-01-22 20:32:11 +08:00
两个人在窗口取餐,谁先谁后肯定要争一争了。
Takamine
2021-01-22 21:01:59 +08:00
channel 只是顺序放在了一个 queue 里,多个 worker 每次谁去取不一定。
useben
2021-01-23 09:24:37 +08:00
底层是锁
kifile
2021-01-23 09:49:14 +08:00
为什么绿皮车比高铁发车早,但是比高铁到的晚呢,这就是原因
zhuzeitou
2021-01-23 10:16:14 +08:00
可以试试 go func 的最后 runtime.Gosched()一下
adamwong
2021-01-23 11:56:42 +08:00
接收是原子的,接收+打印不是

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

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

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

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

© 2021 V2EX