【博客165】子进程如何处理从父进程继承来的锁?

内容: 记录一下,子进程无法得知从父进程继承来的锁,那如何处理从父进程继承来的锁?

问题引出:

在多线程程序中一个线程调用fork,那么是否会产生和父进程一样的线程数呢?答案是:并不会的。
当一个进程产生了子进程,那么子进程会从父进程那里继承过来锁的状态,也就是父进程上了锁,那么这个锁
在子进程也是上着的。那么子进程并不知道从父进程继承来的锁的当前状态是什么,如果其它线程上了锁,
它却不知道,再上锁就可能会出问题,甚至出现死锁,因为如果自己当前就上了锁,它不知道又继续上锁,
就死锁了。

死锁的条件
(1)多个线程:彼此申请对方资源而导致的死锁,A申请B的锁的时候,因为锁被占用所以会把A挂起,
等待B释放锁,同时B申请A的锁,同样因为A的锁被占用,B会被挂起等待,都被挂起没有机会释放锁,
则进入了死锁

(2)单个线程:有自己的锁,但是还要申请新锁,在申请新锁的时候,因为锁被占用,所以会被挂起等待,
但是锁是被自己占用,而自己又被挂起,没机会释放锁,则会进入死锁

问题解决:使用pthread_atfork
函数定义:

#include<pthread.h>
int pthread_atfork(void(*prepare)(void), void(*parent)(void), void(*child)(void));

函数参数解释:

形参:
prepare:将在fork调用创建出子进程之前被执行,它可以给父进程中的互斥锁对象明明确确上锁。这个函数
是在父进程的上下文中执行的,正常使用时,我们应该在此回调函数调用 pthread_mutex_lock 来给
互斥锁明明确确加锁,这个时候如果父进程中的某个线程已经调用pthread_mutex_lock给互斥锁加上了锁,
则在此回调中调用 pthread_mutex_lock 将迫使父进程中调用fork的线程处于阻塞状态,直到prepare
能给互斥锁对象加锁为止。

parent: 是在fork调用创建出子进程之后,而fork返回之前执行,在父进程上下文中被执行。它的作用是
释放所有在prepare函数中被明明确确锁住的互斥锁。

child: 是在fork返回之前,在子进程上下文中被执行。和parent处理函数一样,child函数也是用于释放
所有在prepare函数中被明明确确锁住的互斥锁。

返回值:
     函数成功返回0, 错误返回错误码。

函数用法:

void prepare()
{
	pthread_mutex_lock(&lock);
}

void infork()
{
	pthread_mutex_unlock(&lock);
}

pthread_atfork(prepare,infork,infork);

解释:在prepare传入上锁接口,在另外的两个参数传入解锁接口

大四学生一枚,如果文章有错误的地方,欢迎在下方提出,每条评论我都会去认真看并回复,同时感谢指正的前辈。有喜欢C/C++,linux的同学欢迎私信一起讨论学习。

发布了214 篇原创文章 · 获赞 41 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_43684922/article/details/104450113