fork()与多线程

转自:https://www.techug.com/post/linux-fork.html

在多线程执行的情况下调用fork()函数,仅会将发起调用的线程复制到子进程中。也就是说不能同时创建出于父进程一样多线程的子进程。其他线程均在子进程中立即停止并消失,并且不会为这些线程调用清理函数以及针对线程局部存储变量的析构函数。这将导致下列一些问题:

虽然只将发起fork()调用的线程复制到子进程中,但全局变量的状态以及所有的pthreads对象(如互斥量、条件变量等)都会在子进程中得以保留, 这就造成一个危险的局面。例如:一个线程在fork()被调用前锁定了某个互斥量,且对某个全局变量的更新也做到了一半,此时fork()被调用,所有数 据及状态被拷贝到子进程中,那么子进程中对该互斥量就无法解锁(因为其并非该互斥量的属主),如果再试图锁定该互斥量就会导致死锁,这是多线程编程中最不 愿意看到的情况。同时,全局变量的状态也可能处于不一致的状态,因为对其更新的操作只做到了一半对应的线程就消失了。fork()函数被调用之后,子进程 就相当于处于signal handler之中,此时就不能调用线程安全的函数(用锁机制实现安全的函数),除非函数是可重入的,而只能调用异步信号安全(async- signal-safe)的函数。fork()之后,子进程不能调用:

  • malloc(3)。因为malloc()在访问全局状态时会加锁。
  • 任何可能分配或释放内存的函数,包括new、map::insert()、snprintf() ……
  • 任何pthreads函数。你不能用pthread_cond_signal()去通知父进程,只能通过读写pipe(2)来同步。
  • printf()系列函数,因为其他线程可能恰好持有stdout/stderr的锁。
  • 除了man 7 signal中明确列出的“signal安全”函数之外的任何函数。

2. 因为并未执行清理函数和针对线程局部存储数据的析构函数,所以多线程情况下可能会导致子进程的内存泄露。另外,子进程中的线程可能无法访问(父进程中)由其他线程所创建的线程局部存储变量,因为(子进程)没有任何相应的引用指针。

 

参考:https://www.cnblogs.com/liyuan989/p/4279210.html

posted @ 2022-04-17 14:48  鸪斑兔  阅读(221)  评论(0编辑  收藏  举报