多线程环境使用fork调用

本文探讨了在多线程环境中使用fork函数可能导致的互斥锁状态混乱问题,特别是当子进程继承父进程的锁状态时,可能导致主线程阻塞。文章提供了避免此问题的方法,并讨论了系统库函数中潜在的类似问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 多线程中使用fork存在隐患!

参考下图:
左侧------进程包含主线程,线程A,线程B三个线程以及一个全局互斥锁变量
右侧------线程B通过fork创建一个新的进程,新的进程在虚拟地址空间和左侧的进程空间完全一致(拷贝一份),并且只有一个主线程

1.1 考虑问题

问题情形:
第一步、
左侧的线程A/线程B/主线程当中 任意一个线程在线程B fork之前对互斥锁有Lock操作,前面已经强调了,fork产生的新进程是对父进程地址空间的拷贝

第二步、左侧进程空间互斥锁的lock状态通过fork函数,造成右侧进程得到的互斥锁为lock状态

第三步、右侧主线程在不知情的情况下,对互斥锁加锁,意外发生了,右侧线程会阻塞!

在这里插入图片描述
代码示例:

// An highlighted block
var foo = 'bar';

1.2 读者问题

乐于思考问题的朋友们可能会发问,这个情况我们可以通过多写两行代码避免吧?
自然可以!

诀窍在于:子进程在开始的时候解锁!

下图有个不可不提的地方,线程B在fork之前应当对mutex加锁。
笔者认为主要原因是需要设置mutex为一个明确的状态:Locked,这样线程B后面的unlock操作不会引起同步问题以及子进程直接unlock操作

在这里插入图片描述

2. 线程中fork 须慎用!

我们大家都知道,一个程序的执行可能需要很多的系统库;系统库中相当的库函数都是线程安全的…(使用了锁)

  • 考虑一下,自己写出来的互斥锁,看的见的代码,我们还可以借用1.2一节的方法避免这个问题
  • 但是那么多的系统库函数,也许每一个库函数都有一个锁(这些锁还看不见),比如一个malloc函数,如果从父进程中继承来的malloc互斥锁被加锁,子进程一旦运行malloc就会hang在那里了!!!

3. 推荐链接

pthread_atfork 函数简化了上述过程!

#include <pthread.h>

int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));

参考:
https://blog.youkuaiyun.com/ababab12345/article/details/102897529
https://blog.youkuaiyun.com/codinghonor/article/details/43737869

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值