天天看点

不可重入函数与线程安全函数

      在多线程或有异常控制流的情况下,当某个函数运行到中途时,控制流(也就是当前指令序列)就有可能被打断而去执行另一个函数. 如果在这种情况下不会出现问题,比如说数据或状态不会被破坏,行为确定。那么这个函数就被称做"可重入"的.

补充:

      函数是可重入(reentrant)的,是指对于相同的(并且合法的)函数参数(包括无参函数的情况),多次调用此函数产生的行为是可预期的,即函数的行为一致,或者结果相同。不能保证这一点的函数称为不可重入(non-reentrant)函数。

可重入和线程安全(Thread-Safe)是两个不同的概念:可重入函数一定是线程安全的;线程安全的函数可能是重入的,也可能是不重入的;线程不安全的函数一定是不可重入的。

可重入函数:     Reentrant Function

线程安全函数:   Thread-Safe Function

可重入和线程安全不是一个概念。

可重入 => 线程安全

可重入函数要解决的问题是,不在函数内部使用静态或全局数据,不返回静态或全局数据,也不调用不可重入函数。

线程安全函数要解决的问题是,多个线程调用函数时访问资源冲突。

函数如果使用静态变量,通过加锁后可以转成线程安全函数,但仍然有可能不是可重入的,比如strtok。

strtok是既不可重入的,也不是线程安全的。

加锁的strtok不是可重入的,但线程安全。

而strtok_r既是可重入的,也是线程安全的。

3. reentrant函数与thread safe函数的区别

       reentrant函数与是不是多线程无关,如果是reentrant函数,那么要求即使是同一个进程(或线程)同时多次进入该函数时,该函数仍能够正确的运作.该要求还蕴含着,如果是在多线程环境中,不同的两个线程同时进入该函数时,该函数也能够正确的运作.

thread safe函数是与多线程有关的,它只是要求不同的两个线程同时对该函数的调用在逻辑上是正确的.

从上面的说明可以看出,reentrant的要求比thread safe的要求更加严格.reentrant的函数必是thread safe的,而thread safe的函数未必是reentrant的.

结论:

1. reentrant是对函数相当严格的要求,绝大部分函数都不是reentrant的(APUE上有一个reentrant函数

的列表).什么时候我们需要reentrant函数呢?只有一个函数需要在同一个线程中需要进入两次以上,我们才需要

reentrant函数.这些情况主要是异步信号处理,递归函数等等.(non-reentrant的递归函数也不一定会

出错,出不出错取决于你怎么定义和使用该函数). 大部分时候,我们并不需要函数是reentrant的.

2. 在多线程环境当中,只要求多个线程可以同时调用一个函数时,该函数只要是thread safe的就可以了.

我们常见的大部分函数都是thread safe的,不确定的话请查阅相关文档.

3. reentrant和thread safe的本质的区别就在于,reentrant函数要求即使在同一个线程中任意地进入两次以上,

也能正确执行.

大家常用的malloc函数是一个典型的non-reentrant但是是thread safe函数,这就说明,我们可以方便的

在多个线程中同时调用malloc,但是,如果将malloc函数放入信号处理函数中去,这是一件很危险的事情.

4. reentrant函数肯定是thread safe函数,也就是说,non thread safe肯定是non-reentrant函数不能简单的通过加锁,来使得non-reentrant函数变成 reentrant函数.

"使用的全局变量的函数也不一定是不可重入的。"这句是正确的,只要正确使用就可以了,但是不使用全局变量是写可重入函数的简单方法.

转载地址:http://blog.sina.com.cn/s/blog_a9303fd90101dilj.html

c++

继续阅读