博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
可重入函数与线程安全
阅读量:4149 次
发布时间:2019-05-25

本文共 1113 字,大约阅读时间需要 3 分钟。


一个问题


为了理解可重入函数的概念,我们先来看这样一个例子:

main函数调用insert函数向链表中头插节点node1,插入操作分为两步。

1

假设它刚做完第一步的时候。由于硬件中断使进程切换到内核。再次回用户态之前检查到有信号待处理,于是切换到sighandler函数,sighandler也调用insert函数向同一个链表中头插节点node2。

2

把插入操作的两步都做完之后从sighandler返回内核态,再次回到用户态从main函数调用的insert函数中继续执⾏第⼆步。

3

结果是:main函数和sighandler先后向链表中插入两个节点,而最后只有一个节点node1插入链表中:

4

像这样,两个执行流main和sighandler同时访问insert函数,就会导致结点丢失。类似于insert这种情况的函数就叫做不可重入函数

这里的重入是指:同一时刻一个函数被多个执行流调用

相对的,有可重入函数:只访问自己私有栈的变量和参数。这个例子同样说明:没有线程,一个进程里也会有多个执行流,比如信号的捕捉。

所以,我们可以总结出可称为不可重入函数的3个条件:

1.调用了malloc或free,因为malloc也是用全局链表来管理堆的。

2.调⽤了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使⽤全局数据结构。
3.必须以线程安全的方式实现的系统函数。

从第3条我们可以看出,可重入/不可重入函数与一个概念相关,这就是线程安全


线程安全与可重入函数


首先,我们需要明确线程安全的概念:一个线程对全局变量这种具有全局性的东西的操作影响到别的线程。简单来说,只要一个程序/进程的线程之间没有涉及到对全局变量的操作,那么这个程序/进程就是线程安全的。

这样看来,线程安全和可重入函数貌似是一样的。后者也是只访问自己私有栈的变量和参数,没有访问全局变量。

其实,可重入函数与线程安全并不相同,一般来说,可重入的函数一定是线程安全的,但反过来就不一定成立了。

5

前方高能:一大段文字即将来袭。。。

总结:可重入函数与线程安全的区别与联系

1.线程安全是在多个线程情况下引发的,而可重入函数在只有一个线程的情况下也可以有。

2.线程安全不一定是可重入的,而可重入函数则一定是线程安全的。
3.如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。
4.如果在某函数中将对临界资源的访问加上锁,则这个函数是线程安全的。
5.线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据操作互不影响。
6.可重入函数是线程安全函数的一种,其特点在于它们被多个线程调用时,不会引用任何共享数据。

你可能感兴趣的文章
用go的flag包来解析命令行参数
查看>>
来玩下go的http get
查看>>
队列和栈的本质区别
查看>>
matlab中inline的用法
查看>>
如何用matlab求函数的最值?
查看>>
Git从入门到放弃
查看>>
java8采用stream对集合的常用操作
查看>>
EasySwift/YXJOnePixelLine 极其方便的画出真正的一个像素的线
查看>>
Ubuntu系统上安装Nginx服务器的简单方法
查看>>
Ubuntu Linux系统下apt-get命令详解
查看>>
ubuntu 16.04 下重置 MySQL 5.7 的密码(忘记密码)
查看>>
Ubuntu Navicat for MySQL安装以及破解方案
查看>>
HTTPS那些事 用java实现HTTPS工作原理
查看>>
oracle函数trunc的使用
查看>>
MySQL 存储过程或者函数中传参数实现where id in(1,2,3,...)IN条件拼接
查看>>
java反编译
查看>>
Class.forName( )你搞懂了吗?——转
查看>>
jarFile
查看>>
EJB3.0定时发送jms(发布/定阅)方式
查看>>
EJB与JAVA BEAN_J2EE的异步消息机制
查看>>