• Linux 8:线程



    1. 线程

    1.1 线程定义

    线程是进程内部的一条执行序列或执行路径,一个进程可以包含多条线程;线程是资源调度的基本单位。
    进程:一个正在运行的程序,进程是资源分配的基本单位。
    在这里插入图片描述

    1.2 线程的实现方式

    在操作系统中,线程的实现有以下三种方式:
    ◼ 内核级线程:创建开销较大,可以利用多处理器资源,可能实现并行
    ◼ 用户级线程:创建更多数目线程,创建开销较少;缺点:无法利用多个处理器,只能实现并发
    ◼ 组合级线程:既可以利用多个处理器资源,又可以创建多数量线程。
    在这里插入图片描述
    Linux系统中线程的实现
    内核级线程
    Linux把所有的线程都当作进程来实现,内核没有准备特别的调度算法或是定义特别的数据结构来表明线程。线程仅仅被视为一个与其他进程共享某些资源的进程。

    1.3 进程与线程的区别

    ◼ 进程是资源分配的最小单位,线程是 CPU 调度的最小单位
    ◼ 进程有自己的独立地址空间,线程共享进程中的地址空间
    ◼ 进程的创建消耗资源大,线程的创建相对较小
    ◼ 进程的切换开销大,线程的切换开销相对较小

    1.4 线程创建

    pthread_create() 创建线程 pthread_join() 等待线程结束 pthread_exit() 退出线程

    1.5 线程

    1. 并发运行
    2. 同步线程
    3. 线程安全

    1.6 代码

    main.c

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

    运行结果
    在这里插入图片描述
    test.c

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<unistd.h>
      4 #include<string.h>
      5 #include<pthread.h>
      6 
      7 void*fun(void*arg)
      8 {
      9     int index=*(int*)arg;//获取值
     10     for(int i=0;i<3;i++)
     11     {
     12         printf("index=%d\n",index);
     13         sleep(1);
     14     }
     15 }
     16 int main()
     17 {
     18     pthread_t id[5];
     19     int i=0;
     20     for(;i<5;i++)
     21     {
     22         pthread_create(&id[i],NULL,fun,(void*)&i);//内核创建线程
     23     }
     24     for(i=0;i<5;i++)
     25     {
     26         pthread_join(id[i],NULL);//等待线程结束
     27     }
     28     exit(0);
     29 }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    运行结果
    在这里插入图片描述
    test.c(修改版)
    在这里插入图片描述
    运行结果(按照顺序执行)
    在这里插入图片描述
    thread.c
    在这里插入图片描述
    运行结果
    在这里插入图片描述

    1.7 例题

    对于变量i在多个线程中进行++操作,一个程序100次,另一个程序100次,求一共多少个值?

    答案
    <= 200次
    代码转化为指令

    1.8 进行信号量设置后,进程不存在并行

    thread.c

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<unistd.h>
      4 #include<string.h>
      5 #include<pthread.h>
      6 #include<semaphore.h>
      7 int m_index=1;
      8 sem_t sem;
      9 void*fun(void*arg)
     10 {
     11     for(int i=0;i<1000;i++)
     12     {
     13         sem_wait(&sem);
     14         printf("m_index=%d\n",m_index++);
     15         sem_post(&sem);
     16     }
     17 }
     18 int main()
     19 {
     20     sem_init(&sem,0,1);
     21     pthread_t id[5];//创建5个线程
     22     for(int i=0;i<5;i++)
     23     {
     24         pthread_create(&id[i],NULL,fun,NULL);
     25     }
     26 
     27     for(int i=0;i<5;i++)
     28     {
     29         pthread_join(id[i],NULL);
     30     }
     31     sem_destroy(&sem);
     32     exit(0);
     33 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    运行结果
    在这里插入图片描述

    1.9 信号量控制按照顺序打印A,B,C

    main.c

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

    运行结果
    在这里插入图片描述
    test.c

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<unistd.h>
      4 #include<string.h>
      5 #include<pthread.h>
      6 #include<semaphore.h>
      7 
      8 pthread_rwlock_t rwlock;
      9 
     10 void*fun1(void*arg)
     11 {
     12     for(int i=0;i<5;i++)
     13     {
     14         pthread_rwlock_rdlock(&rwlock);//读锁
     15         printf("a read start...\n");
     16         int n=rand() % 3;
     17         sleep(n);
     18         printf("a read end...\n");
     19         pthread_rwlock_unlock(&rwlock);
     20         n=rand() % 3;
     21         sleep(n);
     22     }
     23 }
     24 void*fun2(void*arg)
     25 {
     26     for(int i=0;i<5;i++)
     27     {
     28         pthread_rwlock_rdlock(&rwlock);//读锁
     29         printf("b read start...\n");
     30         int n=rand() % 3;
     31         sleep(n);
     32         printf("b read end...\n");
     33         pthread_rwlock_unlock(&rwlock);
     34         n=rand() % 3;
     35         sleep(n);
     36     }
     37 }
     38 void*fun3(void*arg)
     39 {
     40     for(int i=0;i<5;i++)
     41     {
     42         pthread_rwlock_wrlock(&rwlock);//写锁
     43         printf("----write start----\n");
     44         int n=rand() % 3;
     45         sleep(n);
     46         printf("----write end----\n");
     47         pthread_rwlock_unlock(&rwlock);
     48         n=rand() % 3;
     49         sleep(n);
     50     }
     51 }
     52 int main()
     53 {
     54     pthread_rwlock_init(&rwlock,NULL);
     55     pthread_t id1,id2,id3;
     56     pthread_create(&id1,NULL,fun1,NULL);
     57     pthread_create(&id2,NULL,fun2,NULL);
     58     pthread_create(&id3,NULL,fun3,NULL);
     59 
     60     pthread_join(id1,NULL);
     61     pthread_join(id2,NULL);
     62     pthread_join(id3,NULL);
     63 
     64     pthread_rwlock_destroy(&rwlock);
     65     exit(0);
     66 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    运行结果
    在这里插入图片描述

    1.10 条件变量

    1.10.1 函数

    pthread_cond_wait() 把线程存放到等待队列 pthread_cond_signal() 唤醒单个线程 pthread_cond_broadcast() 唤醒所有进程

    1.11 唤醒线程

    cond.c

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<unistd.h>
      4 #include<string.h>
      5 #include<pthread.h>
      6 #include<semaphore.h>
      7 
      8 pthread_mutex_t mutex;
      9 pthread_cond_t cond;
     10 
     11 void*funa(void*arg)
     12 {
     13     while(1)
     14     {
     15         char*s=(char*)arg;
     16         pthread_mutex_lock(&mutex);
     17         pthread_cond_wait(&cond,&mutex);
     18         pthread_mutex_unlock(&mutex);
     19 
     20         if(strncmp(s,"end",3)==0)
     21         {
     22             break;
     23         }
     24         printf("a:%s\n",s);
     25     }
     26     printf("funa over\n");
     27 }
     28 
     29 void*funb(void*arg)
     30 {
     31     while(1)
     32     {
     33         char*s=(char*)arg;
     34         pthread_mutex_lock(&mutex);
     35         pthread_cond_wait(&cond,&mutex);
     36         pthread_mutex_unlock(&mutex);
     37 
     38         if(strncmp(s,"end",3)==0)
     39         {
     40             break;
     41         }
     42         printf("b:%s\n",s);
     43     }
     44     printf("funb over\n");
     45 }
     46 
     47 int main()
     48 {
     49     pthread_mutex_init(&mutex,NULL);
     50     pthread_cond_init(&cond,NULL);
     51 
     52     char buff[128]={0};
     53     pthread_t ida,idb;
     54 
     55     pthread_create(&ida,NULL,funa,buff);
     56     pthread_create(&idb,NULL,funb,buff);
     57 
     58     while(1)
     59     {
     60         fgets(buff,127,stdin);
     61 
     62         if(strncmp(buff,"end",3)==0)
     63         {
     64             pthread_cond_broadcast(&cond);
     65             break;
     66         }
     67         else
     68         {
     69             pthread_cond_signal(&cond);
     70         }
     71     }
     72 
     73     pthread_join(ida,NULL);
     74     pthread_join(idb,NULL);
     75 
     76     pthread_cond_destroy(&cond);
     77     pthread_mutex_destroy(&mutex);
     78 }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    运行结果
    在这里插入图片描述
    在这里插入图片描述


  • 相关阅读:
    [附源码]java毕业设计SSM归途中流浪动物收容与领养管理系统
    无胁科技-TVD每日漏洞情报-2022-10-25
    HCIP—OSPF虚链路实验
    文件上传漏洞 解析、验证、伪造(二)
    stereo-inertial-gnss-lidar device
    GAN相关网络用什么归一化方法:BatchNorm?Weight Norm?Layer Norm?
    Mac的nodejs npm run build 报ERR_OSSL_EVP_UNSUPPORTED彻底解决办法
    Redeis缓存查询基于元注解与AOP结合使用——不过时的优雅
    关于如何解决visualc++6.0打开文件闪退的一种方式(附带解决输入法无法显示)
    Flutter 中点击输入框之外的区域,进行失焦,收起键盘
  • 原文地址:https://blog.csdn.net/qq_48580892/article/details/125420999