英文:
golang: strange issue with coroutines and channels
问题
我写了一个测试代码,但不明白为什么会得到这个结果。
我的 sub()
函数应该根据通道的值更新或返回 counter
。
发送 1 = counter++
发送 0 = 返回 counter
我启动了 10 个 con()
协程。它们应该简单地向通道发送很多个 1(这会增加 counter 的值)。
我等待 1 秒钟,然后向通道发送 0。我应该得到什么值?
我认为首先会得到一个“随机”的值,
但我得到了 100000(好吧,10 乘以 10000 比 1 秒钟更快)。
现在我将
for i:=0; i < 10; i++ {
改为
for i:=0; i < 10000; i++ {
现在我的返回值是 1
为什么!?
现在取消 main()
函数中的 fmt.Println(counter)
的注释。
你会看到 counter 起作用,并且有这个“随机”的数字。
package main
import (
"fmt"
"time"
)
var ch chan int = make(chan int)
var counter int
func main() {
go sub()
for i:=0; i < 10; i++ { // 改为 10000
go con()
}
time.Sleep(1000 * time.Millisecond)
ch <- 0
fmt.Println(<- ch)
//fmt.Println(counter) // 取消此行的注释
}
func sub() {
for c := range ch {
if c == 0 { ch <- counter }
if c == 1 { counter++ }
}
}
func con() {
for i := 0; i < 10000; i++ {
ch <- 1
}
}
英文:
I wrote a test code, but do not understand why I get this result.
My sub()
should update or return counter
, based on the channel value
send 1 = counter++
send 0 = return counter
I start 10 go routines con()
.
They should simply send many 1 to channel (this increase counter)
I wait 1 sec and send 0 to channel. What value should I get?
I think first, I get a "random" value,
but i get 100000 (ok 10x 10000 is faster than 1 sec)
Now I change
for i:=0; i < 10; i++ {
to
for i:=0; i < 10000; i++ {
and now my returned value is 1
Why!?
Now uncomment fmt.Println(counter)
in main()
.
As you see counter works and has this "random" number
package main
import (
"fmt"
"time"
)
var ch chan int = make(chan int)
var counter int
func main() {
go sub()
for i:=0; i < 10; i++ { //change to 10000
go con()
}
time.Sleep(1000 * time.Millisecond)
ch <- 0
fmt.Println(<- ch)
//fmt.Println(counter) //uncomment this
}
func sub() {
for c := range ch {
if c == 0 { ch <- counter }
if c == 1 { counter++ }
}
}
func con() {
for i := 0; i < 10000; i++ {
ch <- 1
}
}
答案1
得分: 0
使用2个通道,这段代码的作用是:
package main
import (
"fmt"
"time"
)
var ch chan int = make(chan int)
var ch2 chan int = make(chan int)
var counter int
func main() {
go sub()
for i := 0; i < 10000; i++ { //更改为10000
go con()
}
time.Sleep(1000 * time.Millisecond)
ch2 <- 0
fmt.Println(<-ch2)
//fmt.Println(counter) //取消注释此行
}
func sub() {
for {
select {
case <-ch:
counter++
case <-ch2:
ch2 <- counter
}
}
}
func con() {
for i := 0; i < 10000; i++ {
ch <- 1
}
}
这段代码创建了两个整型通道ch
和ch2
,以及一个整型变量counter
。在main
函数中,启动了一个sub
协程和10000个con
协程。sub
协程通过select
语句监听ch
和ch2
通道的消息,并根据接收到的消息对counter
进行操作。con
协程向ch
通道发送10000次整数1。
在main
函数中,通过time.Sleep
函数等待一段时间,然后向ch2
通道发送0,并从ch2
通道接收结果并打印。最后,取消注释fmt.Println(counter)
可以打印出counter
的值。
英文:
with 2 channels, this work:
package main
import (
"fmt"
"time"
)
var ch chan int = make(chan int)
var ch2 chan int = make(chan int)
var counter int
func main() {
go sub()
for i:=0; i < 10000; i++ { //change to 10000
go con()
}
time.Sleep(1000 * time.Millisecond)
ch2 <- 0
fmt.Println(<- ch2)
//fmt.Println(counter) //uncomment this
}
func sub() {
for ;; {
select {
case <- ch:
counter++
case <- ch2:
ch2 <- counter
}
}
}
func con() {
for i := 0; i < 10000; i++ {
ch <- 1
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论