在单独的进程上运行 Goroutines(多处理)

2024-01-28

我目前有一个 MQTT 代码,可以订阅主题、打印收到的消息,然后向新主题发布进一步的指令。这订阅/打印在一个 Goroutine 中完成,并且出版是在另一个 Goroutine 中完成的。这是我的代码:

var wg, pg sync.WaitGroup
// All messages are handled here - printing published messages and publishing new messages
var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {

wg.Add(1)
pg.Add(1)
    go func() {
        defer wg.Done()
        fmt.Printf("%s\n", msg.Payload())
        //fmt.Println(os.Getpid())
    }()
go func(){
    defer pg.Done()
    message := ""
    //Changing configurations
    if strings.Contains(string(msg.Payload()), "arduinoLED") == true {
        message = fmt.Sprintf("change configuration")
    }
    if  strings.Contains(string(msg.Payload()), "NAME CHANGED") == true{
        message = fmt.Sprintf("change back")
    }
    // Publish further instructions to "sensor/instruction"
    token := client.Publish("sensor/instruction", 0, false, message)
    //fmt.Println(os.Getpid())
    token.Wait()

}()
}

func main() {

    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)

    opts := MQTT.NewClientOptions().AddBroker("tcp://test.mosquitto.org:1883")

    opts.SetDefaultPublishHandler(f)
    // Topic to subscribe to for sensor data
    topic := "sensor/data"

    opts.OnConnect = func(c MQTT.Client) {
        if token := c.Subscribe(topic, 0, f); token.Wait() && token.Error() != nil {
            panic(token.Error())
        }
    }
    // Creating new client
    client := MQTT.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    } else {
        fmt.Printf("Connected to server\n")
    }
    wg.Wait()
    pg.Wait()
    <-c
}

被注释掉的os.Getpid()行是检查我正在哪个进程上运行该 Goroutine。现在它们都显示相同的数字(这意味着两者都在同一进程上运行?)。

我的问题是:我怎样才能运行这两个 Goroutine单独的进程?有办法吗?

Edit:如果这不能完成,我想使用编写此代码channels。这是我的代码:

var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
    sensorData := make(chan []byte)
wg.Add(1)
pg.Add(1)
    go func() {
        defer wg.Done()
        //fmt.Printf("%s\n", msg.Payload())
        sensorData <- string(msg.Payload())
        fmt.Println(<-sensorData) //currently not printing anything
    }()
go func(){
    defer pg.Done()
    message := ""
    //Changing configurations
    if strings.Contains(<-sensorData, "arduinoLED") == true{
        message = fmt.Sprintf("change configuration")
    }
    if strings.Contains(<-sensorData, "NAME CHANGED") == true{
        message = fmt.Sprintf("change back")
    }
    // Publish further instructions to "sensor/instruction"
    token := client.Publish("sensor/instruction", 0, false, message)
    token.Wait()

}()

}

但是,我无法使用通道打印任何数据。我究竟做错了什么?


您可能来自 Python,对吧? ;-)

它有一个名为multiprocessing https://docs.python.org/3/library/multiprocessing.html在它的 stdlib 中,这可以很好地解释为什么你使用 你的问题标题中的这个名字以及为什么你显然 无法解释@JimB 所说的意思

如果需要单独的进程,则需要自己执行

Python 中的“多处理”

问题是,Python 的multiprocessing是一个相当高水平的 它的引擎盖下隐藏着很多东西。 当你产生一个multiprocessing.Process并让它运行 一个函数,真正发生的事情是这样的:

  1. Python解释器创建另一个操作系统的 过程(使用fork(2) http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html在类 Unix 系统上 或者CreateProcess https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425在 Windows 上)并安排 它也可以执行 Python 解释器。

    关键是你现在有两个进程 运行两个Python解释器。

  2. 它被安排在Python解释器中 子进程有办法与Python通信 父进程中的解释器。

    这个“通讯链接”一定涉及某种形式 的IPC https://en.wikipedia.org/wiki/Inter-process_communication@JimB 提到。 根本没有其他方式来传达数据和操作 之间separate加工正是因为商品 现代操作系统提供严格的进程分离。

  3. 当你在进程之间交换 Python 对象 https://docs.python.org/3/library/multiprocessing.html#exchanging-objects-between-processes,两者通信Python 口译员连载 and 反序列化他们在你背后 在通过 IPC 链路发送它们之前以及接收之后 相应地,他们从那里开始。 这是使用以下实现的pickle https://docs.python.org/3/library/pickle.html module.

返回出发

Go 没有任何直接的解决方案 匹配Python的multiprocessing,我真的怀疑它可以 已得到合理实施。

造成这种情况的主要原因主要源于 Go 比 Python 级别低得多,因此它不 Python 有能力做出纯粹的假设 它所管理的价值观类型,并且它还努力拥有 其结构中的隐性成本尽可能少。

Go 还努力避开“框架式”方法 解决问题,并使用“图书馆式”的解决方案 可能的。 (“框架与库”的一个很好的概述 例如,给出here https://medium.com/iquii/applications-vs-frameworks-vs-libraries-c1f1a6122711.) Go 的标准库中有所有可以实现的东西 类似于Python的东西multiprocessing但没有 为此提供了现成的 frakework-y 解决方案。

因此,您可以为此做的就是沿着以下路线滚动:

  1. Use os/exec运行您自己的进程的另一个副本。

    • 确保生成的进程“知道”它已经启动 在特殊的“从属”模式下——采取相应的行动。
    • 使用任何形式的 IPC 与新进程进行通信。 通过交换数据标准 I/O 流 https://en.wikipedia.org/wiki/Standard_streams子进程的据说是 最简单的滚动方式(除非你需要交换 打开的文件,但这是一个更难的话题,所以我们不要离题)。
  2. 使用任何合适的包encoding/等级制度 https://golang.org/pkg/encoding/#section-directories- 例如binary, gob, xml— 序列化 并在交换时反序列化数据。

    据说“首选”解决方案是encoding/gob https://golang.org/pkg/encoding/gob but encoding/json也会做得很好 https://stackoverflow.com/a/68641535/720999.

  3. 发明并实施一个简单的协议来告诉 子进程要做什么以及使用哪些数据, 以及如何将结果传达给主人。

真的值得这么麻烦吗?

我想说不,事实并非如此,原因有很多:

  • Go 没有什么比可怕的更可怕的了GIL https://wiki.python.org/moin/GlobalInterpreterLock, 因此无需回避它即可实现真正的并行性 自然有可能的时候。

  • 内存安全完全掌握在您手中,实现它就是 当你尽职尽责地遵守原则时,并不是那么难 那现在通过通道发送的内容拥有者 收件人。换句话说,通过通道发送值 也是这些价值的所有权的转移。

  • Go 工具链集成了竞争检测器,因此您 可以运行你的测试套件-race标记并创建评估 使用构建您的程序go build -race对于相同的 目的:当以这种方式检测的程序运行时, 一旦检测到任何竞争,竞争检测器就会使其崩溃 不同步的读/写内存访问。 该崩溃导致的打印输出包括 关于什么的解释性消息,以及哪里出错, 与堆栈跟踪。

  • IPC 进展缓慢,因此收益很可能会被损失所抵消。

总而言之,我认为没有真正的理由来分离进程,除非 你正在编写类似电子邮件处理服务器的东西 这个概念自然而然地出现了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在单独的进程上运行 Goroutines(多处理) 的相关文章

随机推荐

  • 使用解析的字符串值过滤 MS SQL 2008 服务器中的日期时间列

    我不确定如何使这个问题的标题更具体 我正在开发 ASP NET MVC3 应用程序 在那里 我使用 jQuery 网格来显示数据库中的数据 并且几乎没有过滤器 其中之一应该允许用户按日期搜索 在我的数据库中Date列看起来像这样 我将选定的
  • 在 PySpark 中获取序列文件格式的文件的 HDFS 文件路径

    我在 HDFS 上的数据是序列文件格式 我正在使用 PySpark Spark 1 6 并试图实现两件事 数据路径包含 yyyy mm dd hh 格式的时间戳 我想将其带入数据本身 我尝试了 SparkContext wholeTextF
  • 使用ggplot2绘制时间序列数据

    我正在做一个项目 需要使用 ggplot2 来绘制时间序列数据 这是我正在使用的数据集 这就是我现在所做的 library ggplot2 library lubridate eur Date lt as Date eur Date ggp
  • 如何将 CodeIgniter 的 set_value 用于数组字段?

    我有一个标记为 amenities 的下拉菜单 它是一个数组 当我使用 CodeIgniter 的 form validation 时 我想使用 set value 正确重新填充它 但我无法做到 有人对此有任何意见吗 查看 Codeigni
  • 如何禁用 Android 设备的强制网络助手?

    当用户通过强制门户连接到开放 WiFi 时 Android 设备将打开带有强制门户 登录页面的浏览器实例 我们想禁用它 因为我们使用应用程序进行登录 我在 Android Marshmallow 中遇到了 CaptivePortal 类 我
  • MVVM + ViewModel 调用的 View 特定功能的实现

    这是我想解决的 问题 我有许多 仅查看 特定功能 例如 在运行时更改视图的资源字典 用于将皮肤从黑色更改为蓝色或其他 保存和恢复 查看特定设置 例如视图大小或用户设置的网格属性 所有这些功能都与 ViewModel 无关 因为它们实际上是特
  • 程序逻辑的可视化表示

    我想通过图表来表示我的程序的逻辑 因为该程序非常复杂 我需要一种方法来向另一个人解释我的程序中发生某些事情的原因和方式 流程图是唯一的选择吗 在 UML 中 不同的图针对不同的事物 使用不同的方法 考虑到我们倾向于倾向于面向对象的方法 我将
  • 为 Windows 8 应用商店应用程序启用“Toast 通知”

    我想为我正在构建的 Windows 8 应用商店应用程序启用 Toast 通知 文档说 只需在应用程序 UI 选项卡的通知部分中将 Toast Capable 选项设置为 是 即可 取自如何选择接收 Toast 通知 http msdn m
  • 错误 APT0000:检索项目的父级时出错:找不到与给定名称“Theme.AppCompat.Light.NoActionBar”匹配的资源。 (APT0000)

    我是 xamarin 工作室的新手 我已将与目标 API 23 相对应的所有必需包添加到我的 android xamarin studio 项目中 将其设置为正确的目标 API 23 但我仍然被下图中的这些错误所困扰 任何提供的帮助将不胜感
  • WPF 工具包 DataGrid 性能

    我有一个包含 6 列的 DataGrid 每列都是一个 RadioButton 以便用户可以在 6 个选项中选择 1 个 大约有100行 我使用 6 个 bool 数据成员创建一个自定义类 然后将数据网格与大约 100 个自定义类对象的列表
  • 读取动画 GIF 帧之间的延迟

    如何读取 GIF 动画每一帧之间的控制块 我对每一帧之间的延迟感兴趣 我查看了 ImageReader 的 Javadoc 但没有看到任何内容 这是我从动画 GIF 中读取所有帧的代码 我如何增强它以读取有关动画 GIF 中嵌入的每个帧的元
  • Python:导入文件并转换为列表

    我需要帮助导入文件并将每一行转换为列表 该文件的示例如下所示 p wfgh 1111 11111 111111 287 48 0 65626 1818 0 4654 21512 02020 0 第一行以 p 开头是标题 其余是子句 每个子句
  • Matlab中复变量的曲线拟合

    我想求解下图所示的方程组 矩阵系统 其中矩阵 A 的分量是复数 角度 theta 从0 to 2 pi有 m 个分区 并且n 9 已知值z x iy 假设矩阵 z 的 x 和 y 为 z 0 1 0148 0 1736 0 9848 0 3
  • 安装模拟器卡在“准备虚拟机”上

    我已经成功安装了 Android 版 VS Emulator 但是当我尝试安装设备时 它卡在 准备虚拟机 上 在此之前 Android VS 模拟器要求在提升模式下运行 显示以下问题 我还附上了 Hyper v 管理器中虚拟交换机的屏幕截图
  • 从 Windows Phone 8 设备检索故障转储

    有没有办法在开发期间从 Windows Phone 8 中获取故障转储 我正在寻找一个与普通 Win32 应用程序崩溃时类似的转储文件 或者类似于崩溃时 iOS 设备上保存的内容 以便稍后进行调查 我的问题具体是关于在崩溃后以某种方式从手机
  • App Engine 上的 Flask-SQLAlchemy 使用以下命令连接到 Cloud Compute Engine 上的 MSSQL 数据库

    我对整个 GCP 非常陌生 我需要为客户的项目部署 Flask 应用程序 考虑到 Google 提供的所有文档 部署应用程序非常简单 而且由于使用灵活的应用程序引擎似乎是最简单的方法 因此我正在尝试使用它 我遇到的问题是尝试连接到在计算引擎
  • getaddrinfo:节点名称或服务名称已提供,或未知

    我有一个 Ruby on Rails 应用程序 正在运行 Mac OS X 10 6 的计算机上部署 出现问题的代码是由delayed job 运行的 仅当通过delayed job运行时才会出现该问题 如果我在控制台中运行它 rails
  • 消除重复的多边形州/国家/地区共享边界

    我正在使用 GEOJSON 绘制带有传单的世界地图 并用虚线绘制边界 如下图所示 The problem I am having is that the line is not shared by two states if two sta
  • 使用 Typescript 导入 Electron 类

    如何将 Electron 类导入 Typescript 文件 以便智能感知正常运行 例如 我想把这个 var BrowserWindow require browser window var app require app app on r
  • 在单独的进程上运行 Goroutines(多处理)

    我目前有一个 MQTT 代码 可以订阅主题 打印收到的消息 然后向新主题发布进一步的指令 这订阅 打印在一个 Goroutine 中完成 并且出版是在另一个 Goroutine 中完成的 这是我的代码 var wg pg sync Wait