可重入函数

可重入函数和不可重入函数,这也是一种竞态条件/竞争执行。

#include<stdio.h>
#include<unistd.h>
#include<signal.h>

int a = 1, b =1;

int sum(int *b, int *a)
{
	(*a)++;
	sleep(3);//sleep只是放大了这一过程,方便看清情况
	(*b)++;
	return *a + *b;
}

void sigcb()
{
	printf(“signal------%d\n”, sum(&a, &b));
}

int main()
{
	signal(SIGINT, sigcb);
	printf(“main------%d\n”, sum(&a, &b));//主流程main进入到sum函数的sleep,这时ctrl+c信号到来,此时又重新进入到sum函数,这就是重入(sum函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数),也就是多个流程(因为sigcb和main是两个不同的流程)“同时”进入到一个函数。
	return 0;
}

函数的可重入:多个执行流同时执行进入相同的函数,不会造成数据二义性以及代码逻辑混乱。
函数的不可重入:多个执行流同时执行进入相同的函数,有可能造成数据二义性以及代码逻辑混乱。
sum函数访问了全局变量,有可能因为重入而造成错乱,像这样的函数称为不可重入函数。
多线程本身就是多个执行流。
当用户设计/使用一个函数的时候在多个执行流中,那么这时候就需要考虑函数的是否可重入情况。如果不会出问题,就可重入;如果有问题,就不可重入。
malloc/free涉及到了全局链表的不受保护的操作,因此是一个不可重入函数。
标准I/O库的很多实现都以不可重入的方式使用全局数据结构。

函数可重入与不可重入的关键点

这个函数中是否对临界资源(在此通常都是全局数据)进行了非原子操作,也就是不受保护的操作。
原子操作是不会被打断的,谁都打断不了,一次性就操作完了。

如果压根就没有对全局数据进行操作,根本就不涉及可重入问题。
a++这个操作本身就不是安全的,这个操作实际上是3步
1、从内存加载到寄存器
2、在寄存器上进行累加操作
3、将数据再返回内存中,这个a++操作依然是可以被打断的。

线程安全不一定是可重入的,而可重入函数则一定是线程安全的,因为如果对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生死锁,因此是不可重入的。
可重入函数和线程安全函数的区别
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值