草庐IT

去 GC 停止我的 goroutine?

coder 2023-07-01 原文

我一直在尝试从更传统的语言(如 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/

有关去 GC 停止我的 goroutine?的更多相关文章

  1. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  2. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

  3. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  4. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  5. ruby-on-rails - 测试我的 Ruby gem:Shoulda::Matchers:Module (NoMethodError) 的未定义方法 `configure' - 2

    我正在开发我的第一个Rubygem,并捆绑了cucumber、rspec和shoulda-matches进行测试。当我运行rspec时,出现以下错误:/app/my_gem/spec/spec_helper.rb:6:in`':undefinedmethod`configure'forShoulda::Matchers:Module(NoMethodError)这是我的gem规范:#my_gem.gemspec...Gem::Specification.newdo|spec|......spec.add_development_dependency"activemodel"spec.a

  6. ruby-on-rails - Heroku 吃掉了我的自定义 HTTP header - 2

    我正在使用Heroku(heroku.com)来部署我的Rails应用程序,并且正在构建一个iPhone客户端来与之交互。我的目的是将手机的唯一设备标识符作为HTTPheader传递给应用程序以进行身份​​验证。当我在本地测试时,我的header通过得很好,但在Heroku上它似乎去掉了我的自定义header。我用ruby​​脚本验证:url=URI.parse('http://#{myapp}.heroku.com/')#url=URI.parse('http://localhost:3000/')req=Net::HTTP::Post.new(url.path)#boguspara

  7. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  8. ruby-on-rails - rspec - 我怎样才能让 "pendings"有我的文本而不仅仅是 "No reason given" - 2

    我有这个代码:context"Visitingtheusers#indexpage."dobefore(:each){visitusers_path}subject{page}pending('iii'){shouldhave_no_css('table#users')}pending{shouldhavecontent('Youhavereachedthispageduetoapermissionic错误')}它会导致几个待处理,例如ManagingUsersGivenapractitionerloggedin.Visitingtheusers#indexpage.#Noreason

  9. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

  10. ruby - 为什么 return 关键字会导致我的 'if block' 出现问题? - 2

    下面的代码工作正常:person={:a=>:A,:b=>:B,:c=>:C}berson={:a=>:A1,:b=>:B1,:c=>:C1}kerson=person.merge(berson)do|key,oldv,newv|ifkey==:aoldvelsifkey==:bnewvelsekeyendendputskerson.inspect但是如果我在“ifblock”中添加return,我会得到一个错误:person={:a=>:A,:b=>:B,:c=>:C}berson={:a=>:A1,:b=>:B1,:c=>:C1}kerson=person.merge(berson

随机推荐