让我解释一下:我已经在Linux上开发了一个应用程序,它Forking 并执行一个外部二进制文件,然后等待它完成.结果通过shm文件传达,这些文件是fork+流程独有的.整个代码封装在一个类中.
现在我正在考虑通过线程来加快进程.拥有许多不同的类函数实例(使用不同的参数)可以并发地Forking 和执行二进制文件,并将结果与它们自己独特的shm文件进行通信.
这个线安全吗?如果我在一根线内Forking ,除了安全之外,还有什么我必须注意的吗?非常感谢您的任何建议或帮助!
让我解释一下:我已经在Linux上开发了一个应用程序,它Forking 并执行一个外部二进制文件,然后等待它完成.结果通过shm文件传达,这些文件是fork+流程独有的.整个代码封装在一个类中.
现在我正在考虑通过线程来加快进程.拥有许多不同的类函数实例(使用不同的参数)可以并发地Forking 和执行二进制文件,并将结果与它们自己独特的shm文件进行通信.
这个线安全吗?如果我在一根线内Forking ,除了安全之外,还有什么我必须注意的吗?非常感谢您的任何建议或帮助!
问题是fork()只复制调用线程,子线程中的任何互斥锁都将永远锁定在fork子线程中.pthread解决方案是pthread_atfork()
个处理程序.我们的 idea 是可以注册3个处理程序:一个预工作处理程序、一个父处理程序和一个子处理程序.当fork()
发生时,在fork之前调用prefork,并期望获得所有应用程序互斥体.父进程和子进程都必须分别释放父进程和子进程中的所有互斥体.
但这并不是故事的结尾!库调用pthread_atfork
为特定于库的互斥体注册处理程序,例如Libc就是这样做的.这是一件好事:应用程序不可能知道由第三方库持有的互斥体,因此每个库必须调用pthread_atfork
,以确保在发生fork()
的情况下清除自己的互斥体.
问题是,为不相关的库调用pthread_atfork
个处理程序的顺序是未定义的(这取决于程序加载库的顺序).因此,这意味着,从技术上讲,由于竞争条件,在预工作处理程序内部可能会发生死锁.
例如,考虑这个序列:
fork()
这就是你的死锁,它与你自己的互斥或代码无关.
这实际上发生在我曾经参与的一个项目上.我当时的建议是 Select fork 或线,但不能两者兼而有之.但对于某些应用程序来说,这可能并不实用.