线程安全与可重入函数

来源:互联网 发布:王珊数据库视频教程 编辑:程序博客网 时间:2024/05/18 04:53

线程安全:如果一个函数在同一时刻可以被多个线程安全地调用,就称该函数是线程安全的。
线程不安全:如果一个函数在同一时刻被不同的线程调用,而出现不同的结果这就是线程不安全。

线程安全函数的作用:解决多个线程调用函数时访问共享资源的冲突问题。
确保线程安全:要确保函数线程安全问题,主要考虑的是线程之间的共享变量

常见的线程不安全函数:
1. 不保护共享变量的函数
2. 函数状态随着被调用,状态发生变化的函数
3. 返回静态变量指针的函数
4. 调用线程不安全的函数

线程不安全的例子:

#include<stdio.h>#include<stdlib.h>#include<pthread.h>int value=0;void* func(void* arg){    int i=0;    while(i<1000)    {        int tmp=value;        printf("value:%d\n",value); //从用户态到内核态之间切换        value=tmp+1;        ++i;    }}int main(){    pthread_t id1,id2;    pthread_create(&id1,NULL,func,NULL);    pthread_create(&id2,NULL,func,NULL);    pthread_join(id1,NULL);    pthread_join(id2,NULL);    printf("main value:%d\n",value);    return 0;}

这里写图片描述

重入函数:函数被不同的控制流控制,有可能在第一次调用还没返回时,就再次进入该函数,则称为
重入函数。
可重入函数:不同的控制流重入函数时,不会造成数据二义性问题。
不可重入函数:重入函数时会造成数据二义性问题,导致对一个变量的操作不可预期。

可重入函数需要满足的条件:
1. 不使用全局变量和静态变量
2. 不使用malloc或new开辟出来的空间
3. 不调用不可重入函数
4. 不返回静态或全局数据,所有数据都由函数调用者提供
5. 一定要使用全局数据,可以在函数内部进行全局的拷贝

例子:

#include<stdio.h>#include<unistd.h>#include<signal.h>int count=0;void fun(){    int i=5;    while(i>0)    {        sleep(1);        i--;        count++;        printf("count:%d\n",count);    }}int main(){    signal(2,fun);    fun();    return 0;}

这里写图片描述

可重入函数与线程安全之间的区别与联系:
1. 线程安全是在多线程之下发生的,而可重入函数可以在只有一个线程下发生。
2. 线程安全函数不一定是可重入函数,可重入函数一定是线程安全函数。
3. 如果一个函数存在全局变量,那么这个函数既不是可重入的也不是,线程安全的。
4. 如果一个函数中的数据全是自身栈空间的,那么这个函数既是可重入的也是线程安全的。
5. 线程安全函数能使不同的线程同时访问同一块地址,而可重入函数要求的是不同执行流对数据的操作
不影响结果。
6. 可重入性要强于线程安全性

原创粉丝点击