Golang中两个协程向同一通道发送消息导致耗时增加10倍的问题
Golang中两个协程向同一通道发送消息导致耗时增加10倍的问题 为什么两个goroutine通过通道发送和接收数据所花费的时间存在如此显著的差异?
golang 版本 1.18 这是我的代码
package main
import (
"log"
"time"
)
type Message struct {
msgID int
timeStamp int64
timeTime time.Time
msgType int
}
func main() {
const buffer = 1000
msgChan := make(chan *Message, buffer)
timeSumType1 := time.Time{}
timeSumType2 := time.Time{}
go func() {
for i := 1; i <= 100; i++ {
time.Sleep(time.Millisecond)
timeT1 := time.Now()
msgChan <- &Message{msgID: i, msgType: 1}
timeDiff := time.Now().Sub(timeT1)
log.Println("type 1, id :", i, " <- timeDelta:", timeDiff)
timeSumType1 = timeSumType1.Add(timeDiff)
}
}()
go func() {
for i := 1; i <= 100; i++ {
time.Sleep(100 * time.Millisecond)
timeT1 := time.Now()
msgChan <- &Message{msgID: i, msgType: 2}
timeDiff := time.Now().Sub(timeT1)
log.Println("type 2, id :", i, " <- timeDelta:", timeDiff)
timeSumType2 = timeSumType2.Add(timeDiff)
}
}()
time.Sleep(time.Second * 20)
log.Println("type 1, timeSum:", timeSumType1)
log.Println("type 2, timeSum:", timeSumType2)
}
第二个goroutine休眠100毫秒,第一个goroutine休眠1毫秒,
第一个goroutine处理消息类型:1 第二个goroutine处理消息类型:2
这是日志: 2024/08/13 15:07:48 type 1, id : 97 ← timeDelta: 375ns 2024/08/13 15:07:48 type 1, id : 98 ← timeDelta: 500ns 2024/08/13 15:07:48 type 1, id : 99 ← timeDelta: 458ns 2024/08/13 15:07:48 type 1, id : 100 ← timeDelta: 417ns
2024/08/13 15:07:48 type 2, id : 2 ← timeDelta: 2.958µs 2024/08/13 15:07:49 type 2, id : 3 ← timeDelta: 20.25µs 2024/08/13 15:07:49 type 2, id : 4 ← timeDelta: 12.583µs
2024/08/13 15:08:08 type 1, timeSum: 0001-01-01 00:00:00.000116749 +0000 UTC 2024/08/13 15:08:08 type 2, timeSum: 0001-01-01 00:00:00.001056743 +0000 UTC
但是,为什么第二个goroutine的发送操作比第一个goroutine花费的时间长好几倍?
是什么内部因素导致了这种差异?
更多关于Golang中两个协程向同一通道发送消息导致耗时增加10倍的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢您的回复。我进一步简化了演示,以直接解决这个问题。我移除了工作协程,这样我们可以专注于发送操作。
更多关于Golang中两个协程向同一通道发送消息导致耗时增加10倍的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
涉及的因素很多,但我认为一个重要的因素可能是哪个 Go 协程在哪个系统线程(也就是 CPU 核心)上执行。 如果两个 Go 协程在同一个线程上执行,它们可以利用一些优化,尤其是在访问共享内存时。 由于 Go 协程是任意分配给操作系统线程的,一种可能的解释是,你的“快速”协程与持续执行代码的工作协程落在了同一个线程上,并且可能因为数据被同一个 CPU 核心访问而获得速度提升。


