3.1线程安全概念
多线程程序无论调度顺序如何,都能得到正确的结果,就处于线程安全的状态。
3.2如何保证线程安全
利用线程同步
使用线程安全函数(可重入函数) 例如:strtok()/strtok_r()
注意自己实现的函数在使用时有没有使用全局变量或者静态变量
3.3分割函数与线程安全
线程安全使用strtok()函数示例:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
void* fun(void* arg)
{
char arr[]={"1 2 3 4 5 6 7 8"};
char*s = strtok(arr," ");
while(s!=NULL)
{
printf("fun=%s\n");
sleep(1);
s=strtok(NULL," ");
}
}
int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
char str[]={"a b c d e f g h"};
char* s=strtok(str," ");
while(s!=NULL)
{
printf("main=%s\n",s);
sleep(1);
s=strtok(NULL," ");
}
pthread_join(id,NULL);
exit(0);
}
运行结果:
原因:
strtok()函数内部只有一个静态变量指针,同一个进程的所有线程在使用strtok()函数时,共用同一个静态变量指针,导致,在第一次主线程中 s 指向 a 后,子线程调用strtok()函数使指针指向从 str 的字符串空间变为 arr 的字符串空间导致之后主线程和子线程都分割的是 arr 中的数据。
解决方法:使用strtok_r()函数
void* fun(void* arg)
{
char arr[]={"1 2 3 4 5 6 7 8"};
char* ptr=NULL;
char*s = strtok_r(arr," ",&ptr);//使用ptr指针去记录每次分割arr字符串后的位置
while(s!=NULL)
{
printf("fun=%s\n");
sleep(1);
s=strtok_r(NULL," ",&ptr);
}
}
int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
char str[]={"a b c d e f g h"};
char* ptr=NULL;
char* s=strtok_r(str," ",&ptr);//使用ptr指针去记录每次分割str字符串后的位置
while(s!=NULL)
{
printf("main=%s\n",s);
sleep(1);
s=strtok_r(NULL," ",&ptr);
}
pthread_join(id,NULL);
exit(0);
}
运行结果正确