函数可重入与线程安全

#基本概念 ##什么是函数的可重入性?

可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反,不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关 键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。

可重入函数:

不为连续的调用持有静态数据。 不返回指向静态数据的指针;所有数据都由函数的调用者提供。 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。 绝不调用任何不可重入函数。

##什么是线程安全?

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行读写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

##函数的可重入性与线程安全之间的关系

可重入的函数不一定是线程安全的; 可重入的函数在多个线程中并发使用时是线程安全的,但不同的可重入函数(共享全局变量及静态变量)在多个线程中并发使用时会有线程安全问题(可能是线程安全的也可能不是线程安全的); 不可重入的函数一定不是线程安全的;

#进程与线程的区别 ##每个线程独立拥有函数调用栈,共享了进程的资源

  • 例如下面这段代码
  • 变量存放在函数的调用栈上,每个线程独立的访问自身的函数调用栈,多线程同时运行时得到的结果相互独立,互不干扰。

void add(int a)
{
	a++;
	printf("%d\n", a);
}
  • 再比如下面这段程序,使用了全局变量,而全局变量存放在堆区,同一进程的多个线程共享堆区,都能对这一区域进行修改,这样就会影响程序的运行正确性
  • 当线程A执行完a++以后正要执行printf,此时另一个线程B也开始执行a++,所以线程A就会打印出a被自加了两次以后得到的结果。

int a = 0;
void add()
{
	a++;
	printf("%d\n", a);
}

##可重入函数

  • 可重入函数是指两个或者多个线程同时进入一个函数内部执行,而不会发生错误
  • 例如上面的那段代码,改一下加个互斥锁
  • 当两个线程同时执行这段代码的时候,要求获得互斥锁,即保证了互斥的访问临界区,在对全局变量写操作之前加上互斥锁,使得函数可重入

int a = 0;
int function()
{
	pthread_mutex_lock(&gplusplus);
	a++;
	printf("%d\n", a);
	pthread_mutex_unlock(&gplusplus);
}

##线程安全

  • 线程安全是指在多线程环境下程序运行能够得到正确的结果
  • 如上面的程序所示,保证了函数是可重入的,可是这并不意味这线程安全
  • 比如有如下两段代码
  • 这两个函数都是可重入函数,但整个代码模块不是线程安全的A函数执行时能写a,B函数执行也能写a
  • 要想保证线程安全,两个函数必须申请同一把锁
  • 线程安全则一定可重入
  • 函数可重入却不一定能保证模块是线程安全的
  • 如果仅仅对临界区的写加了互斥锁,这并不能保证真正线程安全,而是要加入读写锁,即对读操作也要加锁而且要保证高效运行。

int a = 0;
int functionA()
{
	pthread_mutex_lock(&gplusplus);
	a++;
	printf("%d\n", a);
	pthread_mutex_unlock(&gplusplus);
}
int functionB()
{
	pthread_mutex_lock(&gperspers);
	a++;
	printf("%d\n", a);
	pthread_mutex_unlock(&gperspers);
}

转载于:https://my.oschina.net/u/2367621/blog/521371

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值