> 文章列表 > 73-Linux_线程安全

73-Linux_线程安全

73-Linux_线程安全

线程安全

  • 一.什么是线程安全
  • 二.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);}

运行结果截图:
73-Linux_线程安全

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);
}

运行结果截图:
73-Linux_线程安全

三.多线程中执行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);
}