线程

一、线程简介

  一个单独的进程可以看做是一个线程。在创建线程之后,程序运行的地址空间没有发生变化,进程退出变成了线程,有主线程和子线程之分。创建出的主线程和子线程共用地址空间,有各自独立的PCB,子线程的PCB是从主线程中拷贝而来的。

  主线程和子线程共享.text、.data、.bss、堆、环境变量、命令行参数、动态库加载区等,它们之间可通过堆、全局变量通信;

  主线程和子线程不共享的是栈区,如果有多个线程,则栈区被平均分成了多份,各自独立。

  多进程共享的是代码、文件描述符、内存映射区mmap等。相比于多进程,多线程可通过堆、全局变量通信,可节省系统资源。

 

二、线程相关

查看指定线程的LWP号:

先找到程序的进程ID:ps aux

再查看线程的LWP号:ps -Lf pid

 

三、相关函数

相同点:调用成功返回0,失败返回错误号

 

1.创建线程 -- pthread_create

函数原型:int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);

参数:

  thread:线程ID,无符号长整型

  attr:线程属性,默认传NULL

  start_routine:函数指针,传线程处理函数名字

  arg:线程处理函数参数

循环创建线程

 1 #include <stdlib.h>
 2 #include <stdio.h>
 3 #include <pthread.h>
 4 #include <unistd.h>
 5 
 6 void *myfunc(void *num)
 7 {
 8 //      int i = *(int *)num;
 9         int i = (int)num;
10         printf("%dth child thread id:%ld\n",i,pthread_self());
11         return NULL;
12 }
13 
14 int main()
15 {
16         int i;
17         pthread_t pthid[5];
18 
19         for(i=0;i<5;i++){
20                 //第四个参数,传地址的方式
21         //      pthread_create(&pthid[i],NULL,myfunc,(void *)&i);
22                 //传值的方式
23                 int ret = pthread_create(&pthid[i],NULL,myfunc,(void *)i);
24 
25                 if(ret != 0){
26                         printf("error number:%d\n",ret);
27                         //打印错误信息
28                         printf("%s\n",strerror(ret));
29                 }
30         }
31 
32         printf("parent thread id:%ld\n",pthread_self());
33 
34         for(i=0;i<5;i++){
35                 printf("i = %d\n",i);
36         }
37 
38         sleep(2);
39         return 0;
40 }

 

2.单个线程退出 -- pthread_exit

函数原型:void pthread_exit(void *retval);

参数:retval:必须指向全局变量,否则无法传出

注意:如果有线程使用exit(),则会退出所有线程

 1 #include <string.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4 #include <pthread.h>
 5 #include <unistd.h>
 6 
 7 void *myfunc(void *num)
 8 {
 9         printf("child thread id:%ld\n",pthread_self());
10         for(int i=0;i<5;i++){
11                 printf("child i = %d\n",i);
12                 if(i == 2){
13                         pthread_exit(NULL);
14                 }
15         }
16         return NULL;
17 }
18 
19 int main()
20 {
21         pthread_t pthid;
22 
23         int ret = pthread_create(&pthid,NULL,myfunc,NULL);
24 
25         if(ret != 0){
26                 printf("error number:%d\n",ret);
27                 //打印错误信息
28                 printf("%s\n",strerror(ret));
29         }
30 
31 
32         printf("parent thread id:%ld\n",pthread_self());
33         //主线程退出
34         pthread_exit(NULL);
35 
36         for(int i=0;i<5;i++){
37                 printf("i = %d\n",i);
38         }
39 
40         sleep(2);
41         return 0;
42 }

 

3.阻塞等待线程退出,获取线程退出状态 -- pthread_join

函数原型:int pthread_join(pthread_t thread,void **retval);

参数:

  thread:要回收的子线程id

  retval:读取线程退出时候携带的状态信息

    void *ptr;

    pthread_join(pthid,&ptr);

    ptr指向的内存和子进程pthread_exit参数指向的内存为同一个

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <unistd.h>
 4 
 5 int number = 100;
 6 
 7 void *myfunc(void *num)
 8 {
 9         printf("child thread id:%ld\n",pthread_self());
10         for(int i=0;i<5;i++){
11                 printf("child i = %d\n",i);
12                 if(i == 2){
13                         pthread_exit(&number);
14                 }
15         }
16         return NULL;
17 }
18 
19 int main()
20 {
21         pthread_t pthid;
22 
23         int ret = pthread_create(&pthid,NULL,myfunc,NULL);
24 
25         if(ret != 0){
26                 printf("error number:%d\n",ret);
27                 //打印错误信息
28                 printf("%s\n",strerror(ret));
29         }
30 
31 
32         printf("parent thread id:%ld\n",pthread_self());
33 
34         void *ptr = NULL;
35         pthread_join(pthid,&ptr);
36         printf("number = %d\n",*(int *)ptr);
37 
38         for(int i=0;i<5;i++){
39                 printf("i = %d\n",i);
40         }
41 
42         sleep(2);
43         return 0;
44 }

 

4.线程分离 -- pthread_detch

函数原型:int pthread_detch(pthread_t thread);

调用该进程后主进程不需要使用pthread_join,子进程会自己回收自己的pcb

 

5.杀死(取消)进程 -- pthread_cancle

函数原型:int pthread_cancle(pthread_t thread);

注意:在要取消的子进程对应的处理函数内部,必须做过一次系统调用:write、read、printf等

 

6.比较两个线程id是否相等 -- pthread_equal

函数原型:int pthread_equal(pthread_t t1,pthread_t t2);

 

四、线程属性

1.线程属性类型:pthread_attr_t attr

2.线程属性操作函数

 对线程属性初始化:int pthread_attr_init(pthread_attr_t *attr);

 设置线程分离函数:int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate);

    attr:线程属性

    detachstate:PTHREAD_CREATE_DETACHED(分离)

          PTHREAD_CREATE_JOINABLE(非分离)

 释放线程资源函数:int pthread_attr_destroy(pthread_attr_t *attr);

 1 #include <stdio.h>
 2 #include <pthread.h>
 3 #include <unistd.h>
 4 
 5 void *myfunc(void *num)
 6 {
 7         printf("child thread id:%ld\n",pthread_self());
 8         for(int i=0;i<5;i++){
 9                 printf("child i = %d\n",i);
10         }
11         return NULL;
12 }
13 
14 int main()
15 {
16         pthread_t pthid;
17 
18         //设置线程分离
19         pthread_attr_t attr;
20         //初始化行程状态
21         pthread_attr_init(&attr);
22         //设置线程分离属性
23         pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
24 
25         int ret = pthread_create(&pthid,&attr,myfunc,NULL);
26 
27         if(ret != 0){
28                 printf("error number:%d\n",ret);
29                 //打印错误信息
30                 printf("%s\n",strerror(ret));
31         }
32 
33 
34         printf("parent thread id:%ld\n",pthread_self());
35 
36         for(int i=0;i<5;i++){
37                 printf("i = %d\n",i);
38         }
39 
40         sleep(2);
       //释放线程资源 41 pthread_attr_destroy(&attr); 42 43 return 0; 44 }

 

上一篇:js 享元模式


下一篇:基于小熊派的HarmonyOS鸿蒙开发教程——内核篇