linux 线程 创建线程 终止线程 连接已终止的线程 create exit join
创建子线程:
1 /* 2 man pthread: 查询线程系统调用 3 一般情况下, main函数所在的线程称为主线程(main线程),其余创建的线程称为子线程 4 程序中默认只有一个进程,fork()函数调用,2个进程(父子进程) 5 程序中默认只有一个线程(主线程),pthread_create()函数调用,有2个线程(主线程和子线程) 6 #include <pthread.h> 7 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *),) void *arg); 8 - 功能: 创建一个子线程 9 - 参数: 10 - thread:传出参数,线程创建成功后,子线程的线程ID被写到该变量中。 11 - attr: 设置线程的属性, 一般使用默认值,NULL 12 - start_routine: 函数指针,这个函数是子进程需要处理的逻辑代码 13 - arg: 给第三个参数使用,传参 14 - 返回值: 15 成功: 0 16 失败:返回错误号,这个错误号与之前的errno不太一样(不能使用perror()) 17 获取错误号信息: char * strerror(int errnum); (man strerror) 18 */ 19 /* 20 pthread是第三方的库 需要使用 gcc pthread_create.c -o create -l 21 查看 man pthread_create文档( Compile and link with -pthread.) 22 直接使用 gcc pthread_create.c -o create -pthread 23 等同 gcc pthread_create.c -o create -lpthread 24 */ 25 #include <stdio.h> 26 #include <pthread.h> 27 #include <string.h> 28 #include <unistd.h> 29 void * callback(void * arg)//子线程 30 { 31 printf("child thread...\n"); 32 return NULL; 33 } 34 int main()//主线程代码 35 { 36 pthread_t tid;//线程id 37 //创建一个子线程 38 int ret = pthread_create(&tid,NULL,callback,NULL); 39 //如果要创建多个子线程 可以多次调用 pthread_create,子线程的回调函数可以一样也可以不同(另写一个) 40 if(ret != 0) 41 { 42 char * errstr = strerror(ret); 43 printf("error:%s\n",errstr); 44 } 45 for(int i = 0; i < 5; i++)//主线程 可能主线程抢占了CPU资源 执行后return 0 无法进行子线程 46 { 47 printf("%d\n",i); 48 } 49 sleep(1); 50 return 0; 51 }
创建子线程的第四个参数是给第三个回调函数传参:
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <string.h> 4 #include <unistd.h> 5 void * callback(void * arg)//子线程 6 { 7 printf("child thread...\n"); 8 printf("arg value: %d\n",*(int*)arg); 9 //arg是 (void *) 传入进来的是void类型地址, 先转为int型指针地址然后解码取值 10 return NULL; 11 } 12 int main()//主线程代码 13 { 14 pthread_t tid;//线程id 15 int num = 10; 16 //创建一个子线程 17 18 //int ret = pthread_create(&tid,NULL,callback,NULL); 19 //如果要创建多个子线程 可以多次调用 pthread_create,子线程的回调函数可以一样也可以不同(另写一个) 20 int ret = pthread_create(&tid,NULL,callback,(void * )&num);//num的地址传为 void* 指针类型 21 if(ret != 0) 22 { 23 char * errstr = strerror(ret); 24 printf("error:%s\n",errstr); 25 } 26 for(int i = 0; i < 5; i++)//主线程 可能主线程抢占了CPU资源 执行后return 0 无法进行子线程 27 { 28 printf("%d\n",i); 29 } 30 sleep(1); 31 return 0; 32 }
终止线程:
1 /* 2 void pthread_exit(void *retval); 3 功能:终止一个线程,在那个线程中调用,就表示终止那个线程 4 参数: 5 - retval:需要传递一个指针,作为一个返回值,可以在pthrad_join()中获取到 6 返回值:没有返回值 7 8 pthread_t pthread_self(void); 9 功能:获取当前的线程的线程ID 10 11 int pthread_equal(pthread_t t1, pthread_t t2); 12 功能: 比较两个线程ID是否相等 13 不同的操作系统,pthread_t类型实现不一样,有的是无符号的长整型,有的是使用结构体实现的 14 */ 15 #include <stdio.h> 16 #include <pthread.h> 17 #include <string.h> 18 void * callback(void * arg) 19 { 20 printf("child thread id : %ld\n",pthread_self());//在哪里调用,就获取那个线程的ID 21 return NULL;//相当于thred_exit(NULL); 22 } 23 int main() 24 { 25 //创建一个子线程 26 pthread_t tid; 27 int ret = pthread_create(&tid,NULL,callback,NULL); 28 if(ret != 0)// =0 调用成功 29 { 30 char * errstr = strerror(ret); 31 printf("error:%s\n",errstr); 32 } 33 //主线程 34 for(int i = 0; i < 5; i++) 35 { 36 printf("%d\n",i); 37 } 38 printf("tid = %ld, main thread id : %ld\n",tid,pthread_self()); 39 //sleep(1); 40 //让主线程退出,当主线程退出时,不会影响其他正常运行的线程 41 pthread_exit(NULL); 42 printf("main thread exit\n");//打印不出来 已经退出了当前线程 43 return 0;//exit(0); 44 }
连接已终止的线程:pthread_join要在子线程执行完毕后才会执行,否则一直处于阻塞状态
1 /* 2 任何线程都可以回收其他线程(一般是父线程回收子线程资源) 3 int pthread_join(pthread_t thread, void ** retval); 4 - 功能:和一个已经终止的线程进行连接 5 回收子线程的资源 6 这个函数是阻塞函数,调用一次只能回收一个子线程 7 一般在主线程中使用 8 - 参数: 9 - thread:需要回收的子线程ID 10 - retval:接收子线程退出时的返回值 11 - 返回值: 12 0: 成功 13 非0:失败,返回错误号 14 */ 15 #include <stdio.h> 16 #include <pthread.h> 17 #include <string.h> 18 #include <unistd.h> 19 void * callback(void * arg) 20 { 21 printf("child thread id : %ld\n",pthread_self());//在哪里调用,就获取那个线程的ID 22 sleep(3);//3秒阻塞后 pthread_join()执行 23 return NULL;//相当于thred_exit(NULL); 24 } 25 int main() 26 { 27 //创建一个子线程 28 pthread_t tid; 29 int ret = pthread_create(&tid,NULL,callback,NULL); 30 if(ret != 0) 31 { 32 char * errstr = strerror(ret); 33 printf("error:%s\n",errstr); 34 } 35 //主线程 36 for(int i = 0; i < 5; i++) 37 { 38 printf("%d\n",i); 39 } 40 printf("tid = %ld, main thread id : %ld\n",tid,pthread_self()); 41 //主线程调用 pthread_join()回收子线程资源 42 ret = pthread_join(tid,NULL);//不需要获取返回值填入NULL 43 if(ret != 0) 44 { 45 char * errstr = strerror(ret); 46 printf("error: %s\n",errstr); 47 } 48 printf("回收子线程资源成功\n"); 49 //让主线程退出,当主线程退出时,不会影响其他正常运行的线程 50 pthread_exit(NULL); 51 return 0; 52 }
有返回值的情况:
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <string.h> 4 #include <unistd.h> 5 int value = 10;//全局变量 6 void * callback(void * arg) 7 { 8 printf("child thread id : %ld\n",pthread_self()); 9 sleep(3);//3秒阻塞后 pthread_join()执行 10 //int value = 10;//局部变量 thread_retval 为随机值 不准确 11 pthread_exit((void *)& value);//去value值的地址 转化为 void* 类型 为返回值 12 //与 return (void *)&value;相同 13 } 14 int main() 15 { 16 //创建一个子线程 17 pthread_t tid; 18 int ret = pthread_create(&tid,NULL,callback,NULL); 19 if(ret != 0) 20 { 21 char * errstr = strerror(ret); 22 printf("error:%s\n",errstr); 23 } 24 //主线程 25 for(int i = 0; i < 5; i++) 26 { 27 printf("%d\n",i); 28 } 29 printf("tid = %ld, main thread id : %ld\n",tid,pthread_self()); 30 //主线程调用 pthread_join()回收子线程资源 31 int * thread_retval;//线程返回值 32 ret = pthread_join(tid,(void **)&thread_retval);//不需要获取返回值填入NULL 33 if(ret != 0) 34 { 35 char * errstr = strerror(ret); 36 printf("error: %s\n",errstr); 37 } 38 printf("exit data: %d\n",*thread_retval); 39 printf("回收子线程资源成功\n"); 40 //让主线程退出,当主线程退出时,不会影响其他正常运行的线程 41 pthread_exit(NULL); 42 return 0; 43 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)