我听说在程序中混合分叉和线程可能非常有问题,通常会产生神秘的行为,尤其是在处理共享资源时,例如锁,管道,文件描述符。但我从未完全明白危险是什么以及何时会发生。如果具有该领域专业知识的人能够更详细地解释在这样的环境中进行编程时需要注意什么陷阱以及需要注意什么,那就太棒了。
例如,如果我想编写一个从各种不同资源收集数据的服务器,我认为一个解决方案是让服务器生成一组线程,每个popen调用另一个程序来完成实际的工作,打开管道以从孩子那里获取数据。这些线程中的每一个都响应它自己的工作,没有数据交换它们,并且当收集数据时,主线程有一个队列,这些工作线程只将结果放入队列。这个解决方案可能出现什么问题?
请不要仅仅通过“回答”我的示例场景来缩小您的答案范围。任何与示例无关但有助于提供简洁设计的建议,替代解决方案或体验都会非常棒!谢谢!
答案 0 :(得分:17)
当你运行一些线程时,分叉的问题是fork只复制调用它的一个线程的CPU状态。这就好像所有其他线程都会立即死亡,无论它们在哪里。
结果是锁未被释放,共享数据(例如malloc堆)可能已损坏。
pthread确实提供了一个pthread_atfork函数 - 理论上,你可以在分叉之前获取程序中的每一个锁,然后释放它们,并且可能使它活着 - 但它有风险,因为你总能错过一个。当然,其他线程的堆栈也不会被释放。
答案 1 :(得分:0)
这真的很简单。多线程和进程的问题总是来自共享数据。如果没有共享数据,则不会出现任何可能的问题。
在您的示例中,共享数据是主线程拥有的队列 - 此处将出现任何潜在的争用或竞争条件。解决这些问题的典型方法涉及锁定方案 - 工作线程将在插入任何数据之前锁定队列,主线程将在删除之前锁定队列。