在讲可重复函数与线程安全之前先来了解什么是可重复函数和线程安全。
可重复函数:在多线程或有异常控制流的情况下,当某个函数运行到中途时,控制流(也就是当前指令序列)就有可能被打断而去执行另一个函数.而"另一个函数"很有可能是它本身.,如果在这种情况下不会出现问题,比如说数据或状态不会被破坏,行为确定。那么这个函数就被称做"可重入"的。也就是说如果一个函数只访问自己的局部变量或参数,则称为可重入函数(Reentrant) 。
线程安全:一个函数被称为线程安全的(thread-safe),当且仅当被多个并发进程反复调用时,它会一直产生正确的结果。如果一个函数不是线程安全的,我们就说它是线程不安全的(thread-unsafe)。
接下来就来看看他们两者之间有什么区别和联系。
可重入与线程安全并不等同。一般说来,可重入的函数一定是线程安全的,但反过来不一定成立。它们的关系可用下图来表示:
由此可以看出可重入函数是线程安全函数的一种。可重入性就是无论以什么方式多次调用都不会出现问题,不会出现对可能有修改的静态数据的访问,不会出现对全局变量(比如errno)的访问。严格讲可重入要区分线程安全(弱可重入)还是信号安全(强可重入)两点,但是一般说可重入就是指信号安全。这是由于信号安全要求高于线程安全。
因此如果一个函数中用到了全局或静态变量,那么它不是线程安全的,也不是可重入的;
访问全局或静态变量时使用互斥量或信号量等方式加锁,则可以使它变成线程安全的,但此时它仍然是不可重入的,因为通常加锁方式是针对不同线程的访问,而对同一线程可能出现问题;
如果将函数中的全局或静态变量去掉,改成函数参数等其他形式,则有可能使函数变成既线程安全,又可重入。
eg:strtok函数是既不可重入的,也不是线程安全的;加锁的strtok不是可重入的(并发安全但信号不安全,涉及内部静态变量,但线程安全(并发安全);而strtok_r既是可重入的,也是线程安全的。
本文出自 “七月朔风” 博客,请务必保留此出处http://luminous.blog.51cto.com/10797288/1826119
说说可重复函数(Reentrant) 和线程安全(thread-safe)的区别与联系
原文地址:http://luminous.blog.51cto.com/10797288/1826119