线程安全
- 一.什么是线程安全
- 二.strtok和strtok_r
- 1.strtok
- 2.strtok_r
- 三.多线程中执行fork
- 1.多线程中某个线程调用 fork(),子进程会有和父进程相同数量的线程吗?
- 2.父进程被加锁的互斥锁 fork 后在子进程中是否已经加锁 ?
一.什么是线程安全
线程安全即就是在多线程运行的时候,不论线程的调度顺序怎样,最终的结果都是一样的、正确的。那么就说这些线程是安全的。
要保证线程安全需要做到:
1) 对线程进行同步,保证同一时刻只有一个线程访问临界资源。(四个方法)
2) 在多线程中使用线程安全的函数(可重入函数),所谓线程安全的函数指的是:如果一个函数能被多个线程同时调用且不发生竟态条件,则我们程它是线程安全的。
二.strtok和strtok_r
1.strtok
strtok不是一个线程安全函数,它的内部使用了全局变量或者静态变量
代码:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
void *fun(void* arg)
{
char buff[]={"a b c d e f g h"};
char * s=strtok(buff," ");
while(s!=NULL)
{
printf("fun s=%s\n",s);
sleep(1);
s=strtok(NULL," ");
}
}
int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
char arr[]="1 2 3 4 5 6 7 8";
char *s=strtok(arr," ");
while(s!=NULL)
{
printf("main s=%s\n",s);
sleep(1);
s=strtok(NULL," ");
}
pthread_join(id,NULL);
exit(0);
}
运行结果截图:
2.strtok_r
strtok是线程安全函数
代码:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
void *fun(void* arg)
{
char buff[]={"a b c d e f g h"};
char *ptr=NULL;
char * s=strtok_r(buff," ",&ptr);
while(s!=NULL)
{
printf("fun s=%s\n",s);
sleep(1);
s=strtok_r(NULL," ",&ptr);
}
}
int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
char arr[]="1 2 3 4 5 6 7 8";
char *ptr=NULL;
char *s=strtok_r(arr," ",&ptr);
while(s!=NULL)
{
printf("main s=%s\n",s);
sleep(1);
s=strtok_r(NULL," ",&ptr);
}
pthread_join(id,NULL);
exit(0);
}
运行结果截图:
三.多线程中执行fork
1.多线程中某个线程调用 fork(),子进程会有和父进程相同数量的线程吗?
答:fork以后,不管父进程有多少条执行路径,子进程只有一条执行路径;这条执行路径就是fork所在的那条执行路径;
代码:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
void * fun(void*arg)
{
for(int i=0;i<5;i++)
{
printf("fun run pid=%d\n",getpid());
sleep(1);
}
}
int main()
{
pthread_t id;
pthread_create(&id,NULL,fun,NULL);
fork();
for(int i=0;i<5;i++)
{
printf("main run pid=%d\n",getpid());
sleep(1);
}
pthread_join(id,NULL);
exit(0);
}
2.父进程被加锁的互斥锁 fork 后在子进程中是否已经加锁 ?
答:父进程有锁,子进程也被复制了锁;锁的状态取决于fork的那一刻父进程的锁的状态.也就是说锁的状态也会被复制进子进程 ;
代码:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<sys/wait.h>
pthread_mutex_t mutex;
void * fun(void*arg)
{
pthread_mutex_lock(&mutex);
printf("fun lock\n");
sleep(5);
pthread_mutex_unlock(&mutex);
printf("fun unlock\n");
}
void at_lock()
{
pthread_mutex_lock(&mutex);
}
void at_unlock()
{
pthread_mutex_unlock(&mutex);
}
int main()
{
pthread_t id;
pthread_mutex_init(&mutex,NULL);
pthread_atfork(at_lock,at_unlock,at_unlock);
pthread_create(&id,NULL,fun,NULL);
sleep(1);
pid_t pid=fork();
if(pid==-1)
{
exit(0);
}
if(pid==0)
{
printf("子进程将要加锁\n");
pthread_mutex_lock(&mutex);
printf("子进程加锁成功\n");
pthread_mutex_unlock(&mutex);
}
else
{
wait(NULL);//阻塞
printf("main over\n");
}
exit(0);
}