gpt4 book ai didi

go - 在go中使用 sleep 时执行哪个goroutine?

转载 作者:IT王子 更新时间:2023-10-29 02:09:05 27 4
gpt4 key购买 nike

我最近刚接触golang。我对使用 time.sleep 函数时的 goroutine 有疑问。这里是代码。

package main

import (
"fmt"
"time"
)

func go1(msg_chan chan string) {
for {
msg_chan <- "go1"
}
}
func go2(msg_chan chan string) {
for {
msg_chan <- "go2"
}
}
func count(msg_chan chan string) {
for {
msg := <-msg_chan
fmt.Println(msg)
time.Sleep(time.Second * 1)
}
}
func main() {
var c chan string
c = make(chan string)
go go1(c)
go go2(c)
go count(c)
var input string
fmt.Scanln(&input)
}

输出是

go1
go2
go1
go2
go1
go2

我认为当计数函数执行 sleep 函数时,go1 和 go2 将以随机顺序执行。所以输出可能像

go1
go1
go2
go2
go2
go1

当我删除计数功能中的 sleep 代码时。结果如我所料,它是随机的。我被困在这个问题上。谢谢。

最佳答案

首先要注意的是,有三个go例程,而且它们都是相互独立的。唯一将两个 go 例程与计数例程结合在一起的是两个 go 例程发送值的 channel 。

time.Sleep 不会使 go 例程同步。在使用 time.Sleep 时,您实际上是让 count 去例程等待那么长时间,这让其他去例程在 channel 上发送可用于 count go routine 才能收到。

您可以做的另一件事是增加 CPU 的数量,这将为您提供随机结果。

func GOMAXPROCS(n int) int

GOMAXPROCS sets the maximum number of CPUs that can be executing simultaneously and returns the previous setting. If n < 1, it does not change the current setting. The number of logical CPUs on the local machine can be queried with NumCPU. This call will go away when the scheduler improves.

The number of CPUs available simultaneously to executing goroutines is controlled by the GOMAXPROCS shell environment variable, whose default value is the number of CPU cores available. Programs with the potential for parallel execution should therefore achieve it by default on a multiple-CPU machine. To change the number of parallel CPUs to use, set the environment variable or use the similarly-named function of the runtime package to configure the run-time support to utilize a different number of threads. Setting it to 1 eliminates the possibility of true parallelism, forcing independent goroutines to take turns executing.

考虑到 go 例程的输出是随机的,它总是随机的。但是 channel 很可能在 FIFO(先进先出)队列中工作,因为它取决于接收到的 channel 上可用的值。因此,无论要发送的 channel 上可用的值是什么,都让 count 例行等待并打印该值。

举个例子,即使我使用 time.Sleep 输出是随机的:

package main

import (
"fmt"
"time"
)

func go1(msg_chan chan string) {
for i := 0; i < 10; i++ {
msg_chan <- fmt.Sprintf("%s%d", "go1:", i)
}
}
func go2(msg_chan chan string) {
for i := 0; i < 10; i++ {
msg_chan <- fmt.Sprintf("%s%d", "go2:", i)
}
}
func count(msg_chan chan string) {
for {
msg := <-msg_chan
fmt.Println(msg)
time.Sleep(time.Second * 1)
}
}
func main() {
var c chan string
c = make(chan string)
go go1(c)
go go2(c)
go count(c)
time.Sleep(time.Second * 20)
fmt.Println("finished")
}

这有时会导致 race condition这就是我们使用 channel 或 wait.groups 使用同步的原因。

package main

import (
"fmt"
"sync"
"time"
)

var wg sync.WaitGroup

func go1(msg_chan chan string) {
defer wg.Done()
for {
msg_chan <- "go1"
}
}
func go2(msg_chan chan string) {
defer wg.Done()
for {
msg_chan <- "go2"
}
}
func count(msg_chan chan string) {
defer wg.Done()
for {
msg := <-msg_chan
fmt.Println(msg)
time.Sleep(time.Second * 1)
}
}
func main() {
var c chan string
c = make(chan string)
wg.Add(1)
go go1(c)
wg.Add(1)
go go2(c)
wg.Add(1)
go count(c)
wg.Wait()
fmt.Println("finished")
}

现在来到您使用永不结束的 for 循环在 channel 上发送值的部分。因此,如果您删除 time.Sleep,您的进程将挂起,因为循环永远不会停止在 channel 上发送值。

关于go - 在go中使用 sleep 时执行哪个goroutine?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52530081/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com