gpt4 book ai didi

去 GC 停止我的 goroutine?

转载 作者:IT王子 更新时间:2023-10-29 02:15:35 26 4
gpt4 key购买 nike

我一直在尝试从更传统的语言(如 Java 和 C)进入 Go,到目前为止,我一直很享受 Go 提供的深思熟虑的设计选择。但是,当我开始我的第一个“真正的”项目时,我遇到了一个几乎没有人遇到过的问题。

我的项目是一个发送和接收数据包的简单网络实现。一般结构是这样的(当然是简化的):

客户端管理与服务器的net.Conn。此 Client 创建一个 PacketReader 和一个 PacketWriter。它们都在不同的 goroutine 中运行无限循环。 PacketReader 接受一个接口(interface),其中包含一个由客户端实现的 OnPacketReceived 函数。

PacketReader 代码如下所示:

go func() {
for {
bytes, err := reader.ReadBytes(10) // Blocks the current routine until bytes are available.
if err != nil {
panic(err) // Handle error
}
reader.handler.OnPacketReceived(reader.parseBytes(bytes))
}
}()

PacketWriter 代码如下所示:

go func() {

for {
if len(reader.packetQueue) > 0 {
// Write packet
}
}
}()

为了使 Client 阻塞,客户端创建了一个由 OnPacketReceived 填充的 channel ,如下所示:

type Client struct {
callbacks map[int]chan interface{}
// More fields
}

func (c *Client) OnPacketReceived(packet *Packet) {
c.callbacks[packet.Id] <- packet.Data
}

func (c *Client) SendDataBlocking(id int, data interface{}) interface{} {
c.PacketWriter.QueuePacket(data)
return <-c.callbacks[id]
}

现在这是我的问题:reader.parseBytes 函数执行一些密集的解码操作,创建相当多的对象(到 GC 决定运行的程度)。 但是,GC 会暂停当前正在解码字节的读取器 goroutine,然后挂起。描述了一个与我的问题相似的问题 here .我已经确认它实际上是 GC 引起的,因为使用 GOGC=off 运行它会成功运行。

此时,我的 3 个例程如下所示:
- 客户端(主例程):WAITING channel
- Writer: 仍在运行,等待队列中的新数据
- Reader:设置为可运行,但实际上并未运行

不知何故,GC 要么无法停止所有例程以便运行,要么在停止后不会恢复所述 goroutines。

所以我的问题是:有什么方法可以解决这个问题吗?我是 Go 的新手,所以我真的不知道我的设计选择是否非常传统,而且我完全改变我的程序结构。我是否需要更改处理数据包读取回调的方式,是否需要尝试降低数据包解码器的强度?谢谢!

编辑:我正在运行 Go 1.5.1,我将在今天晚些时候尝试获得一个工作示例。

最佳答案

根据 mrd0ll4r s 评论,将作者更改为使用 channel 而不是 slice (我什至不知道为什么我首先这样做)。这似乎为 GC 提供了足够的“机动性”以允许线程停止。添加 runtime.Gosched() 并仍然使用 slice 也可以,但 channel 似乎更“go-esque”。

关于去 GC 停止我的 goroutine?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33364138/

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