linux线程的实现

文章目录

  • 前言
  • 一、Linux系统线程的实现方式
  • 二、线程安全
  • 三、进程创建
    • 1.创建进程上限
    • 2.线程+fork()
    • 3.线程+互斥锁+fork
    • 4.三个线程依次输出ABC


前言

linux线程的实现_第1张图片
用户级:创建开销小,由线程库直接管理。无法使用多处理器资源
内核级:创建开销大,由内核直接管理。可以使用多处理器的资源

一、Linux系统线程的实现方式

Linux实现线程的机制非常独特。从内核的角度来说,它并没有线程这个概念。Linux把所有的线程都当作进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构来表征线程。相反,线程仅仅被视为一个与其他进程共享某些资源的进程。每个线程都拥有唯一隶属于自己的task_struct,所以在内核中,它看起来就就像是一个普通的进程(只是该进程和其他一些进程共享某些资源,如地址空间)。

ps -eLf 可以看到进程中的线程
linux线程的实现_第2张图片


二、线程安全

线程安全:简单来说线程安全就是多个线程并发同一段代码时,不会出现不同的结果,我们就可以说该线程是安全的。

strtok()函数不能在多线程中使用
例如下面的函数:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<assert.h>
  4 #include<unistd.h>
  5 #include<string.h>
  6 #include<pthread.h>
  7 
  8 void* fun(void * arg)
  9 {
     
 10     char buff[] = {
     "1 2 3 4 5 6 7 8 9"};
 11     char *s = strtok(buff," ");
 12     while( s != NULL )
 13     {
     
 14         printf("fun s = %s\n",s);
 15         sleep(1);
 16         s = strtok(NULL," ");
 17     }
 18 }
 19 
 21 int main()
 22 {
     
 23     pthread_t id;
 24     pthread_create(&id,NULL,fun,NULL);
 25 
 26     char str[] = {
     "a b c d e f g k l"};
 27    
 28     char *p = strtok(str," ");
 29     while( p !=  NULL)
 30     {
     
 31         printf("p = %s\n",p);
 32         sleep(1);
 33         p = strtok(NULL," ");
 34     }
 35 
 36     pthread_join(id,NULL);
 37 }

改进方法:使用strtok_r()函数:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<assert.h>
  4 #include<unistd.h>
  5 #include<string.h>
  6 #include<pthread.h>
  7 
  8 void* fun(void * arg)
  9 {
     
 10     char buff[] = {
     "1 2 3 4 5 6 7 8 9"};
 11     char * ptr = NULL;
 12     char *s = strtok_r(buff," ",&ptr);
 13     while( s != NULL )
 14     {
     
 15         printf("fun s = %s\n",s);
 16         sleep(1);
 17         s = strtok_r(NULL," ",&ptr);
 18     }
 19 }
 20 
 21 int main()
 22 {
     
 23     pthread_t id;
 24     pthread_create(&id,NULL,fun,NULL);
 25 
 26     char str[] = {
     "a b c d e f g k l"};
 27     char *ptr  = NULL;
 28     char *p = strtok_r(str," ",&ptr);
 29     while( p !=  NULL)
 30     {
     
 31         printf("p = %s\n",p);
 32         sleep(1);
 33         p = strtok_r(NULL," ",&ptr);
 34     }
 35 
 36     pthread_join(id,NULL);
 37 }


三、进程创建

1.创建进程上限

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<assert.h>
  4 #include<unistd.h>
  5 #include<string.h>
  6 #include<pthread.h>
  7 
  8 void* fun(void * arg)
  9 {
     
 10     while(1)
 11     {
     
 12         sleep(1);
 13     }
 14 }
 15 
 16 int main()
 17 {
     
 18     pthread_t id;
 19     int i = 0;
 20     for(l;i<10000;i++)
 21     {
     
 22         int res = pthread_create(&id,NULL,fun,NULL);
 23         if(res != 0)
 24         {
     
 25             break;
 26         }
 27         printf("i = %d\n",i);
 28     }
 29 
 30     pthread_join(id,NULL);
 31 }

2.线程+fork()

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<assert.h>
  4 #include<unistd.h>
  5 #include<string.h>
  6 #include<pthread.h>
  7 
  8 void *fun(void* arg)
  9 {
     
 10     fork();
 11 
 12     int i = 0;
 13     for(;i<5;i++)
 14     {
     
 15         printf("fun run pid = %d\n",getpid());
 16         sleep(1);
 17     }
 18 }
 19 int main()
 20 {
     
 21     pthread_t id;
 22     pthread_create(&id,NULL,fun,NULL);
 23 
 24     int i = 0;
 25     for(;i<5;i++)
 26     {
     
 27         printf("main run pid = %d\n",getpid());
 28         sleep(1);
 29     }
 30 }
           

3.线程+互斥锁+fork

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<assert.h>
  4 #include<unistd.h>
  5 #include<string.h>
  6 #include<pthread.h>
  7 #include<sys/wait.h>
  8 pthread_mutex_t mutex;
  9 
 10 void *fun(void* arg)
 11 {
     
 12 
 13     pthread_mutex_lock(&mutex);
 14     printf("fun lock!\n");
 15     sleep(5);
 16     pthread_mutex_unlock(&mutex);
 17     printf("fun unlock\n");
 18 }
 19 int main()
 20 {
     
 21     pthread_t id;
 22     pthread_mutex_init(&mutex,NULL);
 23     pthread_create(&id,NULL,fun,NULL);
 24     sleep(1);
 25 
 26     pid_t pid = fork();
 27     assert(pid != -1);
 28 
 29     if(pid == 0)
 30     {
     
 31         printf("child lock start\n");
 32         pthread_mutex_lock(&mutex);
 33         printf("child lock success!\n");
 34         pthread_mutex_unlock(&mutex);
 35         exit(0);
 36     }
 37     wait(NULL);
 38     printf("main over\n");
 39 }

fork()会复制父进程的锁,初始状态由复制时父进程中锁的状态决定。所以该程序会阻塞
解决办法:使用pthread_atfork()对fork进行限制,fork之前加锁,之后解锁。

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<assert.h>
  4 #include<unistd.h>
  5 #include<string.h>
  6 #include<pthread.h>
  7 #include<sys/wait.h>
  8 pthread_mutex_t mutex;
  9 
 10 void fun_lock()
 11 {
     
 12     pthread_mutex_lock(&mutex);
 13 
 14 }
 15 
 16 void fun_unlock()
 17 {
         
 18     pthread_mutex_unlock(&mutex);
 19 }
 20 void *fun(void* arg)
 21 {
        
 22     
 23     pthread_mutex_lock(&mutex);
 24     printf("fun lock!\n");
 25     sleep(5);
 26     pthread_mutex_unlock(&mutex);
 27     printf("fun unlock\n");
 28 }
 29 int main()
 30 {
        
 31     pthread_atfork(fun_lock,fun_unlock,fun_unlock);
 32     pthread_t id;
 33     pthread_mutex_init(&mutex,NULL);
 34     pthread_create(&id,NULL,fun,NULL);
 35     sleep(1);
 36     
 37     pid_t pid = fork();
 38     assert(pid != -1);
 39     
 40     if(pid == 0)
 41     {
     
 42         printf("child lock start\n");
 43         pthread_mutex_lock(&mutex);
 44         printf("child lock success!\n");
 45         pthread_mutex_unlock(&mutex);
 46         exit(0);
 47     }
 48     wait(NULL);
 49     printf("main over\n");
 50 }

4.三个线程依次输出ABC

题目说明:三个线程,第一个线程输出A,第二个线程输出B,第三个线程输出C(要求:第一个要输出A,A输出完成之后才能输出B,B输出完成之后才能输出C。例如:ABCABCABC)

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<assert.h>
  4 #include<unistd.h>
  5 #include<string.h>
  6 #include<pthread.h>
  7 #include<semaphore.h>
  8 
  9 sem_t sem1;
 10 sem_t sem2;
 11 sem_t sem3;
 12 
 13 
 14 void* fun1(void* arg)
 15 {
     
 16     int i = 0;
 17     for(;i<5;i++)
 18     {
     
 19         sem_wait(&sem1);//ps1
 20         printf("A");
 21         fflush(stdout);
 22         sem_post(&sem2);//vs2
 23     }
 24 }
 25 
 26 void* fun2(void* arg)
 27 {
     
 28     int i = 0;
 29     for(;i<5;i++)
 30     {
     
 31         sem_wait(&sem2);//ps2
 32         printf("B");
 33         fflush(stdout);
 34         sem_post(&sem3);//vs3
 35     }
 36 }
 37 void* fun3(void* arg)
 38 {
     
 39     int i = 0;
 40     for(;i<5;i++)
 41     {
     
 42         sem_wait(&sem3);//ps3
 43         printf("C");
 44         fflush(stdout);
 45         sem_post(&sem1);//vs1
 46     }
 47 }
 48 int main()
 49 {
     
 50     sem_init(&sem1,0,1);
 51     sem_init(&sem2,0,0);
 52     sem_init(&sem3,0,0);
 53 
 54     pthread_t id[3];
 55     pthread_create(&id[0],NULL,fun1,NULL);
 56     pthread_create(&id[1],NULL,fun2,NULL);
 57     pthread_create(&id[2],NULL,fun3,NULL);
 58 
 59     int i = 0;
 60     for(;i<3;i++)
 61     {
     
 62         pthread_join(id[i],NULL);
 63     }
 64 
 65     sem_destroy(&sem1);
 66     sem_destroy(&sem2);
 67     sem_destroy(&sem3);
 68 
 69 
 70 }

输出结果:ABCABCABCABCABC


你可能感兴趣的:(linux)