创建子线程的逻辑相比子进程要更容易理解一些,因为线程没有像进程那样复制很多东西另起炉灶,子线程从传入的开始函数开始运行,但是难点在于传入参数和回收时获取退出状态,因为这两个原本都是void *类型的,而我们在使用时就必须进行转换。先上代码,然后再根据代码进行解释:

void pthread_check(int ret, const std::string msg = "error", int default_ret = 0);using std::cout;
using std::endl;
namespace {pthread_mutex_t mutex1;
}void *func(void * argc) {//    int idx = *reinterpret_cast<int *>(argc);int idx = reinterpret_cast<long>(argc);pthread_mutex_lock(&mutex1);cout << "I am thread " << idx << "\n";pthread_mutex_unlock(&mutex1);//pthread_exit(argc);return argc;
}void create_multi_thread() {pthread_mutex_init(&mutex1, nullptr);constexpr int N = 5;pthread_t tid[N];void *ret;for (int i = 0; i < N; ++i) {pthread_check(pthread_create(&tid[i], nullptr, func, reinterpret_cast<void *>(i)));}pthread_mutex_lock(&mutex1);cout << "I am thread 5" << "\n";pthread_mutex_unlock(&mutex1);for (int i = 0; i < N; ++i) {pthread_join(tid[i], &ret);pthread_mutex_lock(&mutex1);cout << "thread " << i << " exits with status : " << reinterpret_cast<long>(ret) << "\n";pthread_mutex_unlock(&mutex1);}pthread_exit(0);
}

其中pthread_check函数是我写的一个用于检查返回值的工具函数,mutex1是互斥量用于加锁控制输出(否则可能会很乱),子线程的工作很简单,就是输出自己是第几个线程。

  • 其中比较关键的地方就是pthread_create的第四个参数:向开始函数传参。这里我们可以看到把循环变量i转换使用reinterpret_cast转换成了void *类型的,然后再在开始函数func中使用reinterpret_cast函数将void *类型转换成了long类型。

    你可能觉得奇怪,为什么要把一个int类型直接转换成void *类型,为什么不将其地址传入呢?首先,要想清楚为什么使用void *类型作为传入参数的类型:我认为指针类型比基本类型更加广泛,指针类型可以保存基本类型的值,也可以指向内存,但是基本类型是无法指向内存的值的,因此使用空指针类型灵活度更高,这里仅仅是这个场景下需要传入一个整数而我们不想大费周章在堆上分配内存罢了,如果分配内存的话显然是需要指针的。

    可不可以传入int值的地址而不是将其本身传入进去呢?如果是单个线程应该是没有什么问题,但是多个子线程下就有问题了:因为该函数的栈空间是线程共享的,因此当主控线程修改了循环变量的值以后子线程中的值也会被修改,这显然不是我们想要的,如果还是感觉到无法理解的话可以自己手动尝试一下。

  • 第二个问题就是为什么要在func函数中使用reinterpret_castvoid *转换为long类型而不是int类型,因为在C++里面转换成int类型会报错说精度丢失(虽然C语言里面好像不会,我看大家都在随便转,感觉这个转换太魔性了,还是C++规范一些),但是一般情况下long类型和指针类型的大小是差不多大的,转换成 long类型就不用担心精度丢失了。

  • 第三个问题就是在使用pthread_join函数回收子线程的时候我们使用ret来获取子线程退出状态,经过测试发现在子线程的开始函数的返回值就是最后的子线程退出状态(当然我们也可以使用pthread_exit函数)

  • ret本身是void *类型,pthread_join函数需要一个void **类型,用来接收返回的void *类型,在接收成功后我们再次将其转换成long类型。

运行结果如下:

Linux创建多个子线程并回收相关推荐

  1. 树莓派 | threading01 - 创建两个子线程同时运行,两个线程各负责控制一个LED灯以不同的频率闪烁

    文章目录 一.前言 二.代码 三.运行 一.前言 Python | threading01 - 创建两个同时运行的子线程 上一次使用了python的多线程库threading创建了两个同时运行的子线程 ...

  2. Linux系统编程:fork函数的使用【循环创建N个子线程】

    fork函数介绍 在linux下面进行系统编程,一定要养成一个好习惯,不懂的函数 直接 找男人,用man 指令进行查看,虽然是全英文 但是要强迫自己 学会看英文文档!下面是介绍,我们看重点. FORK ...

  3. Linux系统编程:循环创建N个子线程并顺序输出

    实现代码 代码很简单,如下.但是也有坑!在给线程传参数的不能穿 循环遍历i 的 地址,因为 i 在主线程中 ,被多个线程共享,所以不是唯一的.那么如何让每个线程 都有独自拥有自己的顺序编号呢? 1.方 ...

  4. linux创建多个子进程,[Linux进程]使用fork函数创建多个子进程

    #include #include int main (void) { pid_t pid1,pid2;   //进程标识符 pid1 = fork();      //创建一个新的进程 if(pid ...

  5. Java 多线程练习---创建两个子线程,每个线程交替输出“你好--来自线程***”...

    |--需求说明 |--实现思路 1.创建一个类,实现Runnable,在这个类里面重写run()方法,在run()方法里面写一个20的for循环 2.创建一个类,实例化上面的类,用这个类的对象创建线程 ...

  6. linux创建10个子进程,linux父进程创建两个子进程

    #include"stdio.h" #include"stdlib.h" //exit包含在stdlib.h头文件中 #include"unistd. ...

  7. Linux创建4个线程P1 P2,HYZ-OS-2017-2-进程管理-4.ppt

    HYZ-OS-2017-2-进程管理-4 * * 北京交通大学计算机学院何永忠 管程的引入 基于信号量的进程同步机制的弊端 各临界资源访问进程均须自备同步操作 大量同步操作分散不利于系统管理 同步操作 ...

  8. linux之使用 pthread_join 函数将循环创建的多个子线程回收

    代码:pthrd_loop_join.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #i ...

  9. Linux系统编程---14(回收子线程,回收多个子线程,线程分离,杀死线程)

    回收子线程 pthread_join 函数 阻塞等待线程退出,获取线程退出状态 其作用,对应进程中 waitpid() 函数. int pthread_join (pthread_t thread,v ...

最新文章

  1. [转]在Fedora上安装Oracle 11g XE
  2. 问题合集 ------- 用 Eclipse 平台进行 C/C++ 开发
  3. AutoCode For XML(XML解析代码生成器)发布
  4. 我的Go+语言初体验——(6)整型有理数数据类型
  5. oracle约束的相关总结
  6. android 微信摇一摇动画效果
  7. 漫话CLR ---- 属性
  8. 码农们的聚餐,会复杂到什么程度?
  9. 这行简单的网址可令Chrome立马崩溃
  10. android+1m的大小,android raw读取超过1M文件的方法
  11. 编写MapReduce程序,实现WordCount
  12. sbt启动机制、配置优化及与Intellij IDEA的集成
  13. TCP/IP协议栈扫盲班
  14. 计算机前沿应用,计算机前沿技术总结范文
  15. FPGA------------ SRIO通信(1)发送
  16. IDEA控制台设置查找快捷键
  17. 那些我离不开的 Sketch 插件
  18. 01.什么是数学建模
  19. 康耐视VisionPro
  20. 数据分析 常见异常及解决办法(一)

热门文章

  1. PotPlayer安装与配置
  2. CPU-内存-IO-网络调优
  3. UML学习(一)-----用例图
  4. Linux历史,安装,分区,版本
  5. easyui 插入中间行
  6. java学习笔记总略
  7. 【Centos】yum 安装mariaDB
  8. MVC3学习 一 ViewBag和Html.Raw
  9. 使用ACE_SOCK_SEQPACK_Association获取socket连接的本地及远程IP端口信息
  10. oracle走当前时间分区,Oracle分区使用波斯日历的时间间隔