创建的线程数超出预期

2024-04-21

你可以找到该程序here https://pastebin.com/H5fq732a

我正在消息传递框架 0MQ 中构建一个程序。我尝试执行我发布的内容here https://stackoverflow.com/questions/44096203/another-reliable-way-to-do-pull-push-sync-in-zeromq

程序编译为g++ -std=c++11 test.cpp -o test -lzmq -lpthread.

要运行该程序,请传递一个参数作为您想要的线程号。然后将该参数分配给变量worker_num.

在主线程中,我设置线程:

  vector<thread> pool;
  for(int i = 0; i < worker_num; i++)
  {
    cout << "main() : creating thread, " << i << endl;
    pool.push_back(thread(task1, (void *)&context, i));
  }

我想确保所有工作线程在主线程将作业分发给它们之前都已成功连接到主线程。

  while(true)
  {
    if(sync_done)
    {
      cout << "sync done in main thread" << endl;
      break;
    }

    zmq::message_t sync_msg(4);
    memcpy((void *)sync_msg.data(), SYNC_MSG, SYNC_MSGLEN);
    for(int i = 0; i < worker_num; i++)
      distask_socket.send(sync_msg);

    for(int i = 0; i < worker_num; i++)
    {
      if(sync_done)
        break;
      if(i != 0)
        this_thread::sleep_for(chrono::milliseconds(500));

      zmq::message_t res_msg;
      int ret = getres_socket.recv(&res_msg, ZMQ_DONTWAIT);

      if(ret == -1 && errno == EAGAIN)
        continue;

      int threadID = stoi(string((char *)res_msg.data()));
      sync_done = if_sync_done(threadID, sync_array, worker_num);
    }
  }

那么主线程所做的就是:push #worker_num ofsync每次将其 PUSH 端点发送到工作线程,然后从其 PULL 端点读取确认消息。如果主线程检索到 #worker_num 的确认消息,则同步完成。来自工作线程的同步消息的格式为:字符串中的工作线程 ID。所以线程 0 会传递一个0在字符串中返回主线程。

但是运行我的程序:

$ ./test 1
main() : creating thread, 0
thread id:0
thread 0 receives: sync
thread 0 sends: 0
thread 0 sync done
main thread receives sync msg from thread 1 # you may get many copies of this msg
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi
Aborted

main thread receives sync msg from thread 1意味着创建了 2 个线程:线程 0 和线程 1。知道为什么吗?我确实通过了1作为参数。请注意,如果您自己运行该程序,您可能会得到其他输出。

UPDATE:

计划更新:here https://pastebin.com/USDVwehY.

最后我明白出了什么问题。

预期输出,您会看到线程 0 传递了 a0到主线程通知同步完成:

$ ./test 1
input parameter is: 1
main() : creating thread, 0
thread 0 receives: sync
to_string 0
thread 0 sends: 0, with size: 1
thread 0 sync done
pass 0 to if_sync_done
main thread receives sync msg from thread 0
sync done in main thread

意外的输出,您会看到不可打印的字符被传递给stoi():

$ ./test 1
input parameter is: 1
main() : creating thread, 0
thread 0 receives: sync
to_string 0
thread 0 sends: 0, with size: 1
thread 0 sync done
pass  to if_sync_done  # !!!!!
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi
Aborted

所以看来我用message_t错误地。所以我需要确保在主线程将内容传递给之前stoi(),缓冲区仍然存在。

我自己添加一个答案。


zmq::message_t msg_back((void *)to_string(id).c_str(), to_string(id).size() + 1, NULL);

zmq::message_t你使用的构造函数确实not复制缓冲区,如果[1] http://rtbkit.org/dox/0.9/zmq_8hpp_source.html#l00101 and [2] http://api.zeromq.org/2-1:zmq-msg-init-data是值得相信的。相反,它获取缓冲区的所有权。

但是,您正在传递一个由临时管理的缓冲区;一旦构造函数返回,该缓冲区就会被销毁。你有msg_back存储一个悬空指针。任何使用该指针的尝试 - 例如尝试在接收端读取消息 - 表现出未定义的行为。

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

创建的线程数超出预期 的相关文章

随机推荐

  • Android Studio 1.0.2 m2respository gradle问题

    使用Android Studio 1 0 2 并且强制使用Gradle 2 2 1 所有系统变量都是正确的 在新的更新中 旧版本的 gradle 和 m2repository 存在问题 我正在尝试导入 kickflip io android
  • 如何手动调用(查找)ReCaptcha Callback函数?

    我目前正在尝试验证码解决 并决定使用流行的 2captcha 服务来实现此目的 他们的方法是向他们发送验证码值 谷歌验证码密钥和站点线程 然后他们解决它并向我发回应该发送给谷歌的完成值 以检查验证码是否已解决 我被困在最后一步 使用返回的解
  • 包装 API 以支持依赖注入

    我正在与一个只有静态函数的 API 进行交互 并且无法打开和更改 public class WindowsNativeGraphAPI public static IEnumerable
  • 练习:网络爬虫 - 并发不起作用

    我正在经历 golang 之旅 并致力于最后的练习 以将网络爬虫更改为并行爬行而不是重复爬行 http tour golang org 73 http tour golang org 73 我所改变的只是抓取功能 var used make
  • Android Resources$NotFoundException:无法找到资源 ID

    我从 Firebase 收到一份活动报告 由于找不到我的资源而导致活动失败 我真的很困惑为什么找不到它 因为我相信所有文件都在正确的目录中 并且用户使用的是 Android v8 1 它并不古老 应该能够处理我认为有的东西自 v1 1 以来
  • 强制用户注销会话 PHP

    我似乎无法找到这个问题的直接答案 有没有办法强制登录用户注销 我的登录系统本质上只依赖于包含用户唯一 ID 存储在 mysql 数据库中 的会话 所以本质上只是 if isset SESSION user id echo You re lo
  • Delphi XE2:为什么 FireMonkey 应用程序是高清的?

    根据 Delphi XE2 的发行说明 FireMonkey可以创建高清应用程序 HD 代表高清晰度 为什么是高清 VCL应用程序不能像FireMonkey一样创建高清应用程序吗 这里是Firemonkey 的文档 http docwiki
  • 来自 post 请求的有效负载在 Node.js 函数中不可用

    我刚刚开始摆弄三个新的 对我来说 框架 产品 MongoDB NodeJS 和 AngularJS 我想要完成的是让一个简单的表单提交一个值并将该值写入数据库 我已经到了这样的地步 在我的 Angular 应用程序中使用 http post
  • jQuery 中的对象或方法链接如何工作?

    我不是问链接的适当语法是什么 我知道它可能是这样的 myDiv removeClass off addClass on 据我所知 链接是相对于其他著名框架的优势之一 有人可以向我解释一下链接在这里是如何工作的吗 如果您有一个具有某些方法的对
  • 参数“sectionGroupName”无效

    我正在尝试添加服务引用 然后收到此错误 参数 sectionGroupName 无效 参数名称 sectionGrouName 项目运行 Net 3 5 当我将项目升级到 Net 4 0 时 它就可以工作了 但这对我来说不是一个选择 因为其
  • 为什么按钮不绘制?

    我不明白为什么按钮不绘制在它之前工作的背景上 这不会显示错误 这是代码 gt 这段代码是错误的吗 我的问题是否可以重现 它可能在按钮的代码中 我将不胜感激 import pygame pygame init screen pygame di
  • Kafka服务器未远程连接zookeeper服务器

    我正在尝试将 kafka 服务器 在 Windows 系统上 连接到 Zookeeper 服务器 我面临着 Opening socket connection to server 10 160 10 25 10 160 10 25 2181
  • Postmates 与 Shopify Shipping/Carrier 服务集成

    我们正在寻求集成此应用程序 https postmates com developer docs https postmates com developer docs进入我们的 Shopify 平台 有关其工作原理 请检查 http blo
  • 如何替换ng-view中的部分节?

    我倾向于 Angular 的路线 很清楚如何通过简单的设置将视图加载到 ng view 中template属性 假设我在视图上有一个小部件 当用户导航到 changeWidget 时 如何仅替换小部件内容 在我看来 我只能使用单个ng vi
  • android:errorMessageBackground 在 styles.xml 中找不到资源错误

    我正在研究EditText验证并使用 setError 显示错误消息 我的主要座右铭是根据我的应用程序设计更改错误弹出窗口 我用的是 android errorMessageBackground 风格但不幸的是我得到了 No Resourc
  • 将非标准 svn 转换为 git

    我们有一个非标准的 svn 设置 如下所示 Root gt Trunk gt Projects gt Project 1 gt Project 2 gt Project 3 gt Libraries gt Library 1 gt Libr
  • 使用 ggplot 包 R 更改图中 yaxis 面的标签

    这是我的数据集和生成绘图的代码 library reshape library ggplot2 set seed 357 myLetters lt function length out a lt rep letters length ou
  • 使用 Google Sign-In Android 获取用户的出生日期和性别

    我已经集成了Google Sign In在我的应用程序中 我可以获得用户的Email and DisplayName 现在 我想获取用户的Birthdate and Gender 我已经添加了所有必需的requests Scopes int
  • 对象和 console.log 的奇怪行为[重复]

    这个问题在这里已经有答案了 这段代码 foo id 1 id 2 id 3 id 4 id 5 console log foo1 foo foo length foo splice 2 1 console log foo2 foo foo
  • 创建的线程数超出预期

    你可以找到该程序here https pastebin com H5fq732a 我正在消息传递框架 0MQ 中构建一个程序 我尝试执行我发布的内容here https stackoverflow com questions 4409620