Go channels 似乎没有阻塞,尽管应该是
Go channels seem not to be blocking although supposed to be
我是 golang 的新手,很难理解通道的工作原理。我的理解是,默认情况下,通道应该是阻塞的,所以我希望写入通道的 goroutine 会被调度程序冻结,直到另一个 goroutine 读取通道内容。所以我尝试了下面的代码,它给出了相应的输出:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
var v int
func main() {
ch := make(chan string)
wg.Add(2)
go func(ch chan string) {
fmt.Println("Ready to receive")
for msg := range ch {
fmt.Println("received: ", msg)
fmt.Println(v)
}
wg.Done()
}(ch)
go func(ch chan string) {
fmt.Println("Will send the SMS to mama")
ch <- "msg 1"
v += 1
fmt.Println("Done! sent the message 1")
ch <- "msg 2"
v += 1
fmt.Println("Done! sent the message 2")
ch <- "msg 3"
v += 1
fmt.Println("Done! sent the message 3")
close(ch)
wg.Done()
}(ch)
wg.Wait()
}
输出:
Will send the SMS to mama
Ready to receive
received: msg 1
0
Done! sent the message 1
Done! sent the message 2
received: msg 2
2
received: msg 3
2
Done! sent the message 3
我有点惊讶,因为我期待以下顺序:
- 第 1 条消息已发送
- 收到消息 1
- 第 2 条消息已发送
- 收到消息 2
等等。但事实显然并非如此。
有人知道为什么 Go 会这样吗?非常感谢,
这里是 link 代码 https://play.golang.org/p/O6SXf0CslPf. And here are my sources for stating what I said earlier: https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb https://rakyll.org/scheduler/
这种行为是完全正常的,所以回答你的问题
so I expect a goroutine that writes into a channel to be frozen by the scheduler until an other goroutine reads the channel content
除非需要进一步同步,否则在通过通道发送值后,调度可能会也可能不会继续同一个 goroutine。
所以例如 "msg 2" 发送到 ch
并在下一行中的另一个 goroutine 中读取
ch <- "msg 2"
goroutine 可以继续执行 v += 1
并在其他 goroutine 调用它之前调用 fmt.Println
。
从不同的 goroutines 调用 fmt.Println
也需要同步,并且可能 mutex
调用也可能重新排序打印语句。
此外还有变量 v
的数据竞争
我是 golang 的新手,很难理解通道的工作原理。我的理解是,默认情况下,通道应该是阻塞的,所以我希望写入通道的 goroutine 会被调度程序冻结,直到另一个 goroutine 读取通道内容。所以我尝试了下面的代码,它给出了相应的输出:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
var v int
func main() {
ch := make(chan string)
wg.Add(2)
go func(ch chan string) {
fmt.Println("Ready to receive")
for msg := range ch {
fmt.Println("received: ", msg)
fmt.Println(v)
}
wg.Done()
}(ch)
go func(ch chan string) {
fmt.Println("Will send the SMS to mama")
ch <- "msg 1"
v += 1
fmt.Println("Done! sent the message 1")
ch <- "msg 2"
v += 1
fmt.Println("Done! sent the message 2")
ch <- "msg 3"
v += 1
fmt.Println("Done! sent the message 3")
close(ch)
wg.Done()
}(ch)
wg.Wait()
}
输出:
Will send the SMS to mama
Ready to receive
received: msg 1
0
Done! sent the message 1
Done! sent the message 2
received: msg 2
2
received: msg 3
2
Done! sent the message 3
我有点惊讶,因为我期待以下顺序:
- 第 1 条消息已发送
- 收到消息 1
- 第 2 条消息已发送
- 收到消息 2
等等。但事实显然并非如此。
有人知道为什么 Go 会这样吗?非常感谢,
这里是 link 代码 https://play.golang.org/p/O6SXf0CslPf. And here are my sources for stating what I said earlier: https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb https://rakyll.org/scheduler/
这种行为是完全正常的,所以回答你的问题
so I expect a goroutine that writes into a channel to be frozen by the scheduler until an other goroutine reads the channel content
除非需要进一步同步,否则在通过通道发送值后,调度可能会也可能不会继续同一个 goroutine。
所以例如 "msg 2" 发送到 ch
并在下一行中的另一个 goroutine 中读取
ch <- "msg 2"
goroutine 可以继续执行 v += 1
并在其他 goroutine 调用它之前调用 fmt.Println
。
从不同的 goroutines 调用 fmt.Println
也需要同步,并且可能 mutex
调用也可能重新排序打印语句。
此外还有变量 v