Linux多线程中fork与互斥锁过程示例

 更新时间:2021年11月30日 11:26:25   作者:code-016  
大家好,本篇文章主要讲的是Linux多线程中fork与互斥锁过程示例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下哦

问题提出:

我们有这样一个问题:在一个多线程程序中创建子进程并且让子线程子进程去获取一把全局变量的锁,输出子线程得到锁,然后解锁,子进程拿到锁,然后解锁;

(一)初次尝试

代码:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/wait.h>

pthread_mutex_t mutex;

void* fun(void* arg)
{
	pthread_mutex_lock(&mutex);	
	printf("fun get lock\n");
	sleep(3);

	pthread_mutex_unlock(&mutex);
	printf("fun unlock\n");
}
int main()
{
	pthread_mutex_init(&mutex, NULL);
	pthread_t id;
	pthread_create(&id, NULL, fun, NULL);
	
	sleep(1);
	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork err");
		return -1;
	} 

	if(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("child get lock\n");
		sleep(3);
		
		pthread_mutex_unlock(&mutex);
		printf("child unlock\n");
		exit(0);
	}
	
	wait(NULL);

	pthread_mutex_destroy(&mutex);
	printf("main over\n");
	return 0;
}

猜想结果:

理一理思路:

创建一把全局的锁,并初始化
主线程创建子线程,去获取这把锁的同时,主线程休眠一秒,子线程得到这把锁,加锁fun get lock
子线程休眠3秒,输出解锁fun unlock,子线程退出
主线程开始fork,子进程得到这把锁,输出child lock
子进程解锁输出child unlock
父进程的主线程等待子进程的退出,最后销毁锁,输出main over
所以…直接得到正确代码!!!

(二)理性分析

很遗憾,答案是错的!!!

我们先来康康运行结果:正常输出了子线程的内容,但是。。。。卡住了?没错阻塞了。。

在这里插入图片描述

再次分析:

阻塞??难道是子进程获取锁时阻塞了?还是父进程等待子进程阻塞了?
或者说:两处地方都阻塞了,子进程获取锁时阻塞,导致父进程阻塞。
验证一下!!

在这里插入图片描述

所以程序就是两处地方都阻塞了,子进程获取锁时阻塞,导致父进程阻塞。

(三)解决问题

实际上,我们子线程在获取这把锁并加锁后睡眠3秒,主线程睡眠1秒,在主线程1秒睡眠结束后,开始执行fork,此时的子线程还未解锁正处于睡眠状态,fork过程中,会直接复制父进程的所有资源(**包括这把锁、锁的状态**),没错

就是有两把锁。此时子线程进行了加锁的状态,所以子线程复制的锁也是加锁状态。所以子线程会正常退出,而子进程会因为拿到加锁的锁而阻塞,父进程wait因为子进程阻塞而阻塞;

(1)使用pthread_join()

fork之前使用pthread_join()在子线程结束之前,主线程都将会阻塞,等待子线程结束后,在进行fork,此时子进程得到的锁就是解锁状态

代码:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/wait.h>

pthread_mutex_t mutex;

void* fun(void* arg)
{
	pthread_mutex_lock(&mutex);	
	printf("fun get lock\n");
	sleep(3);

	pthread_mutex_unlock(&mutex);
	printf("fun unlock\n");
}
int main()
{
	pthread_mutex_init(&mutex, NULL);
	pthread_t id;
	pthread_create(&id, NULL, fun, NULL);
	pthread_join(id, NULL);
	
	sleep(1);

	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork err");
		return -1;
	} 

	if(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("child get lock\n");
		sleep(3);

		pthread_mutex_unlock(&mutex);
		printf("child unlock\n");
		exit(0);
	}
	
	wait(NULL);

	pthread_mutex_destroy(&mutex);
	printf("main over\n");
	return 0;
}

结果:

在这里插入图片描述

(2)使用phread_atfork()注册一个fork之前的判断

头文件 : pthread.h

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

prepare : fork执行之前调用该函数

parent : fork执行之后父进程调用该函数

child : fork执行之后子进程调用该函数

返回值: 成功0,失败错误码

代码:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/wait.h>

pthread_mutex_t mutex;

void prepare_fun(void)
{
	pthread_mutex_lock(&mutex);
}

void parent_fun(void)
{
	pthread_mutex_unlock(&mutex);
}

void child_fun()
{
	pthread_mutex_unlock(&mutex);
}

void* fun(void* arg)
{
	pthread_mutex_lock(&mutex);	
	printf("fun get lock\n");
	sleep(3);

	pthread_mutex_unlock(&mutex);
	printf("fun unlock\n");
}

int main()
{
	
	pthread_mutex_init(&mutex, NULL);
	pthread_t id;
	pthread_atfork(prepare_fun, parent_fun, child_fun);
	pthread_create(&id, NULL, fun, NULL);
	
	sleep(1);

	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork err");
		return -1;
	} 

	if(pid == 0)
	{
		pthread_mutex_lock(&mutex);	
		printf("child get lock\n");
		sleep(3);

		pthread_mutex_unlock(&mutex);
		printf("child unlock\n");
		exit(0);
	}
	
	wait(NULL);

	pthread_mutex_destroy(&mutex);
	printf("main over\n");
	return 0;
}

结果:

在这里插入图片描述

到此这篇关于Linux多线程中fork与互斥锁过程示例的文章就介绍到这了,更多相关Linux多线程fork与互斥锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Ubuntu部署python3.5的开发和运行环境

    Ubuntu部署python3.5的开发和运行环境

    这篇文章主要介绍了Ubuntu部署python3.5的开发和运行环境,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • 配置apache支持apk ipk下载的方法

    配置apache支持apk ipk下载的方法

    这篇文章主要介绍了配置apache支持apk ipk下载的方法,需要的朋友可以参考下
    2014-04-04
  • linux如何开启apache服务

    linux如何开启apache服务

    这篇文章主要介绍了linux如何开启apache服务,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-11-11
  • CentOS7 mini的安装和静态ip设置教程

    CentOS7 mini的安装和静态ip设置教程

    本篇文章主要介绍了CentOS7 mini的安装和静态ip设置教程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • Apache多路复用模块(MPMs)介绍

    Apache多路复用模块(MPMs)介绍

    这篇文章主要介绍了Apache多路复用模块(MPMs)介绍,MPM,也叫多道处理模块(Multi Processing Module),关系到整个HTTP会话,本文就介绍它的相关知识,需要的朋友可以参考下
    2015-01-01
  • linux &、nohup与Systemctl的使用

    linux &、nohup与Systemctl的使用

    这篇文章主要介绍了linux &、nohup与Systemctl的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • 详解在linxu下Svn一键安装shell脚本

    详解在linxu下Svn一键安装shell脚本

    这篇文章主要介绍了在linxu下Svn一键安装shell脚本的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • CentOS 6 启动流程详细介绍

    CentOS 6 启动流程详细介绍

    这篇文章主要介绍了CentOS 6 启动流程详细介绍的相关资料,这里对centos 启动进行了分析,希望能帮助到大家理解centos 启动流程,需要的朋友可以参考下
    2017-07-07
  • 详解Linux环境变量配置全攻略

    详解Linux环境变量配置全攻略

    这篇文章主要介绍了Linux环境变量配置全攻略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • Linux命令行之使光标快速移动的快捷键

    Linux命令行之使光标快速移动的快捷键

    这篇文章主要介绍了Linux命令行之使光标快速移动的快捷键,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11

最新评论