C/C++
线程安全和函数可重入
可重入和线程安全, 这2个是完全不同的概念;
可重入函数只有在signal下会发生, 比如一个函数在执行时被中断, 在中断处理函数中又一次被调用, 这2次(每次)调用都能产生正确的结果,那就个可重入函数;
可重入函数
看一个不可重入的例子:
void sig_handler(int sig)
{
...
gethostbyname("www.baidu.com");
....
alarm(1);
}
int main()
{
signal(SIGALRM,sig_handler);
alarm(1);
while(1){
....
gethostbyname("www.google.com");
printf(...);
}
return 0;
}
gethostbyname 内部实现有一个静态局部变量, 或一个静态全局变量;
这意味着, 在main中gethostbyname的调用刚执行完或者只执行了一半, 此时signal来了, 转到sig_handler继续调用gethostbyname ,由于实现是一个静态变量,因此后调用gethostbyname将把前一次的数据覆盖.
因此可以想象, 如果一个函数内部使用了静态/全局变量来做数据处理或者返回此静态/全局变量,那么一定是一个不可重入函数;
线程安全
简单来说就是加锁操作;
那么线程安全的函数就一定是可重入的吗 ? 答案是否定的
例如:
malloc 是线程安全的,他将操作一个全局链表 , 一旦在执行过程中被sigal中断,直接完蛋
pthread_mutex_lock 他是线程安全吧, 一旦执行过程中被中断, 中断处理中又一次pthread_mutex_lock可能直接死锁或者破坏了内部状态
在比如:,线程安全? 能在中断之后正确的执行吗?
int func(){
static int i = 0;
lock ;
++i;
unlock ;
return i;
}
总之线程安全跟可重入是2个概念 , 虽然他们之间有些交集;
一个函数中如果使用了静态/全局变量, 那他基本是一个不可重入的函数,当然具体还是看实现;如果此函数中加了
锁,那么他是线程安全的, 如果内部也把静态/全局变量都删了, 也不额外调用不可重入函数的话,那他就是一个
即线程安全也可重入的函数了 .
最后 , 一个可重入的函数 是一个线程安全的函数 ?
不一定 ; 只不过一般情况可重入的函数是线程安全的,
原因:
你自己想嘛 , 不可重入函数的特点就是 [ 使用或返回了静态/全局变量 或 使用了额外的不可重入函数 ]
那么可重入函数必然不调用或不使用那些玩意,