文档章节

函数可重入与线程安全

qsctwh
 qsctwh
发布于 2015/10/23 20:02
字数 1172
阅读 48
收藏 0

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

可重入(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);
}

© 著作权归作者所有

共有 人打赏支持
qsctwh
粉丝 0
博文 6
码字总数 3415
作品 0
苏州
私信 提问
Linux — 线程安全和可重入函数

线程安全和可重入函数 线程安全:一个函数被称为线程安全的(thread-safe),当且仅当被多个并发进程反复调用时,它会一直产生正确的结果。如果一个函数不是线程安全的,我们就说它是线程不安...

Dawn_sf
2017/07/02
0
0
对于可重入、线程安全、异步信号安全几个概念的理解

可重入与异步信号安全 一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误。 ...

长平狐
2012/09/03
152
0
Signal处理中的函数可重入问题

Signal信号简介 信号是软件层次上模拟的中断,它是一种异步通信的处理机制。信号的异步性意味着,应用程序不用等待事件的发生,当信号发生时应用程序自动陷入到对应的信号处理函数中。产生信...

pnsam301
07/17
0
0
可重入函数与线程安全函数

1).线程安全函数:一般说来,一个函数被称为线程安全的,当且仅当被多个并发线程反复调用时,它会一直产生正确的结果。 2).可重入:程序执行到某个函数foo()时,收到信号,于是暂停目前正在执...

长平狐
2012/09/03
195
0
可重入性和线程安全

可重入性就是线程安全吗?很多人包括我自己起初都不过分区分它们,实际上也没有过分它们的必要,程序员是干活的,就像民工只要浇铸混凝土就可以了,然而如果程序员对一些平常的操作知其所以然...

晨曦之光
2012/04/10
141
0

没有更多内容

加载失败,请刷新页面

加载更多

docker部署springboot项目

安装docker 菜鸟教程 springboot项目 maven依赖 <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001......

yimingkeji
今天
10
0
ios多个target

1.建立3个target,分别为heroone,heroone test,heroone dev;分别为正式环境,test环境,dev环境 2.注意取消掉autocreate以防止名字不对,分别以Duplicate的方式建立另外两个scheme 3.创建...

HeroHY
今天
6
0
php获取客户端IP

php获取客户端IP 首先先阅读关于IP真实性安全的文章:如何正確的取得使用者 IP? 「任何從客戶端取得的資料都是不可信任的!」 HTTP_CLIENT_IP头是有的,但未成标准,不一定服务器都实现。 ...

DrChenXX
昨天
0
0
. The valid characters are defined in RFC 7230 and RFC 问题

通过这里的回答,我们可以知道: Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后,添加了对于http头的验证。 具体来说,就是添加了些规则去限制HTTP头的规范性 参考这里 具体来说: org.apache.tom...

west_coast
昨天
1
0
刷leetcode第704题-二分查找

今天双十一买的算法书到货了,路上刷到有人说的这个题,借(chao)鉴(xi)一下别人的思路,这个是C++标准库里面的经典方法,思路精巧,优雅好品味 int search(int* nums, int numsSize, in...

锟斤拷烫烫烫
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部