我正在使用valgrind运行多线程套接字程序。客户端将通过TCP向服务器发送请求,然后忙于等待布尔值。当调用服务器响应服务的回调函数时,将设置布尔值。一旦收到响应(并设置了布尔标志),服务器将再次发出请求,并在循环中重复执行此操作。
我意识到对共享变量的非同步访问(布尔值)可能会导致线程问题,但我尝试使用pthread互斥,并且程序减慢了大约20%(速度在这里很重要)。我有信心写共享布尔变量很好,因为它可以在一个循环中完成。
该程序在valgrind之外运行良好,但在使用valgrind运行时经常会失速。我让程序一夜之间运行..通常需要几秒钟才能完成,所以我不认为这是一个不等待程序完成的情况。线程由开源引擎框架(快速修复)管理,所以我认为这不是创建/管理线程的问题。
有没有人知道valgrind在多线程程序/忙等待循环/套接字通信(或这些的组合)周围的任何问题?
答案 0 :(得分:8)
虽然其他答案侧重于坚持采用标准同步方法(我完全赞同的方式),但我想我应该回答你关于Valgrind的问题。
据我所知,Valgrind在多线程环境中运行没有问题。我相信Valgrind强制应用程序在单个核心上运行,但除此之外它不应该影响你的线程。
Valgrind可能对您的应用程序做了什么改变了线程之间的时间和交互方式,可能会暴露代码中的错误和竞争条件,而这些错误和竞争条件是您在独立运行时通常看不到的。
在我看来,您应用于判断错误不在您正在使用的开源线程框架中的相同逻辑也适用于Valgrind。我建议您将这些挂起视为代码中的错误并进行调试,因为这很可能是它们的原因。
作为旁注,使用互斥锁对于您描述的问题可能有点过分。您应该调查信号量或条件变量。
祝你好运。答案 1 :(得分:3)
读取/写入布尔值不是x86上的原子操作。
在此处查看我的问题:Is volatile a proper way to make a single byte atomic in C/C++?
答案 2 :(得分:2)
即使编写boolean是一个原子操作,compiler and the CPU are free to re-order the update围绕其他内存访问。忙碌的等待线程可能会从繁忙的循环中醒来,发现共享数据结构不实际上已经更新。
我强烈建议您坚持使用可用的线程原语来编写一致的程序,这些程序每次都按照您的意愿执行。
答案 3 :(得分:1)
我也有类似的问题。像OP一样,我有一个线程在忙着等待。就我而言,问题是繁忙的等待几乎占用了所有CPU周期,并导致其他线程的运行速度慢了数千倍。最初,我通过将usleep(1)放入繁忙的等待循环中来解决此问题(仅适用于Valgrind构建)。然后,我阅读了Valgrind手册,并了解了--fair-sched = yes选项,该选项还解决了该问题,并允许我删除usleep(1)。