【linux c多线程】线程的创建,线程信息的获取,获取线程返回值

线程创建

专栏内容

  • 参天引擎内核架构
    本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。

  • 手写数据库toadb
    本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。
    本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,方便阶段学习。

开源贡献

  • toadb开源库

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

  • 线程创建
  • 前言
  • 概述
  • 线程介绍
  • 创建线程
  • 退出线程
  • 获取返回值
  • 线程信息
  • 示例代码
  • 总结
  • 结尾

前言

现代的CPU都是多core处理器,而且在intel处理器中每个core又可以多个processor,形成了多任务并行处理的硬件架构,在服务器端的处理器上架构又有一些不同,传统的采用SMP,也就是对称的多任务处理架构,每个任务都可以对等的访问所有内存,外设等,而如今在ARM系列CPU上,多采用NUMA架构,它将CPU核分了几个组,给每个组的CPU core分配了对应的内存和外设,CPU访问对应的内存和外设时速度最优,跨组访问时性能会降底一些。

随着硬件技术的持续发展,它们对一般应用的性能优化能力越来越强,同时对于服务器软件的开发,提出更高要求,要想达到极高的并发和性能,就需要充分利用当前硬件架构的特点,对它们进行压榨。那么,我们的应用至少也是要采用多任务架构,不管是多线程还是多进程的多任务架构,才可以充分利用硬件的资源,达到高效的处理能力。

当然多任务框架的采用,不仅仅是多线程的执行,需要对多任务下带来的问题进行处理,如任务执行返回值获取,任务间数据的传递,任务执行次序的协调;当然也不是任务越多处理越快,要避免线程过多导致操作系统夯住,也要防止任务空转过快导致CPU使用率飙高。

本专栏主要介绍使用多线程与多进程模型,如何搭建多任务的应用框架,同时对多任务下的数据通信,数据同步,任务控制,以及CPU core与任务绑定等相关知识的分享,让大家在实际开发中轻松构建自已的多任务程序。

概述

本文主要分享多线程的创建,退出,以及线程属性的设置,线程执行返回等相关posix API,以及流程。

在多任务架构搭建中,常常使用多线程方式,因为线程相较于进程,是一种轻量级的任务,也是最小的任务单元,还有一个关键点是,线程间的通信方式更加灵活和方便,相反的进程间通信就必须要借助内核手段。

线程的使用流程,主要包括线程的创建启动,线程的退出,线程任务返回值获取,线程信息的管理等几方面。

在linux中我们采用posix线程库进行介绍,在编译时需要增加 -lpthread,头文件需要包括 # include <pthread.h>

线程介绍

我们已经知道线程是一种轻量级的任务单元,它是在进程中创建,共享当前进程的内存上下文,也就是说线程是在进程的控制之下,进程不存在时,线程也就会退出,这就是“皮之不存,毛将焉附”。

另外一个重要特点是,线程的内存模型,同一进程中的所有线程共享当前进程的内存空间,这就是说不同线程对全局变量的修改,都是相互可以看到的,动态内存申请的内存也是可以相互传递的,同时局部静态变量也是共享的。

创建线程

在linux 创建线程,需要指定线程的描述符,线程的任务执行函数,以及它的入参,当然也可以对线程的属性进行设置。

  • 创建线程的函数
#include <pthread.h>
int pthread_create(pthread_t *restrict thread,const pthread_attr_t *restrict attr,void *(*start_routine)(void *),void *restrict arg);
  • 参数说明
    thread , 线程描述符,记录线程句标识;

attr, 线程属性,可以线程行为进行控制;

start_routine, 线程执行的主函数;声明格式为 void * func(void *pointer);

arg, 主函数的入参,因为主函数是由线程调度程序自动调用的,参数必须在创建时指定。

退出线程

线程的退出,可以通过以下几种方式:

  • start_routine 线程执行函数正常返回,如函数完成时执行return ;
  • 调用线程退出函数 pthread_exit, 这相当于执行函数提前退出;
  • 使用线程控制函数 pthread_cancel,让某一线程退出;
  • 线程所在的进程退出,或者调用exit,或者主函数main返回了,这都会导致该进程下的所有线程退出。

获取返回值

很多时候,线程执行结束后,都会带有返回值,调用者需要根据返回值决定任务执行的情况,如何获取线程执行函数的返回值呢?

同一进程下的各线程间的关系是平等的,只要知道了线程的标识后,调用下面的函数就可以获取对方的返回值。

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
  • 参数说明
    thread, 线程的标识,创建线程时会得到;

retval, 返回码;由pthread_exit或者return 返回;

  • 函数说明

调用者调用此函数后会被阻塞,至到thread标识的线程返回为止。

线程信息

线程在创建以后,除了调用者可以获取线程标识外,线程本身也可以通过函数获取自己的标识。

#include<pthread.h>
pthread_t pthread_self(void)

示例代码

示例代码位置

multipleThreads/example_01threadCreate.c
Makefile 

代码如下:

/* * created by senllang 2023/12/24 * mail : study@senllang.onaliyun.com * Copyright (C) 2023-2023, senllang*/
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>void *thread(void *arg) 
{char *ret;printf("thread() entered with argument '%s'\n", arg);if ((ret = (char*) malloc(20)) == NULL) {perror("malloc() error");exit(2);}strcpy(ret, "This is a test");pthread_exit(ret);
}int main(int argc, char *argv[]) 
{pthread_t thid;void *ret;if (pthread_create(&thid, NULL, thread, "thread 1") != 0) {perror("pthread_create() error");exit(1);}if (pthread_join(thid, &ret) != 0) {perror("pthread_create() error");exit(3);}printf("thread exited with '%s'\n", ret);
}

编译时,需要在加上线程库 lpthread ,运行结果如下:

[senllang@hatch example_01]$ ll
total 8
-rw-r--r--. 1 senllang develops 1265 Dec 24 20:32 Makefile
-rw-r--r--. 1 senllang develops  781 Dec 24 20:33 threadCreate.c
[senllang@hatch example_01]$ make
gcc  -I./ -DTEST_PRO -lpthread -g -c threadCreate.c
gcc  -I./ -DTEST_PRO -lpthread -g *.o -o hatch-0-01
[senllang@hatch example_01]$ ll
total 40
-rwxr-xr-x. 1 senllang develops 21368 Dec 24 20:34 hatch-0-01
-rw-r--r--. 1 senllang develops  1265 Dec 24 20:32 Makefile
-rw-r--r--. 1 senllang develops   781 Dec 24 20:33 threadCreate.c
-rw-r--r--. 1 senllang develops  7600 Dec 24 20:34 threadCreate.o
[senllang@hatch example_01]$ ./hatch-0-01 
thread() entered with argument 'thread 1'
thread exited with 'This is a test'

总结

本文重点分享了线程的创建使用,在main中需要等待线程的结束,因为它是当前进程的主线程,如果它提前结束,由它创建的所有线程也会提前结束,所以它需要等待所有线程结束之后,才能退出。

后面会继续介绍更多线程的知识,完成一个通用线程池的功能。

所有示例的代码已经上传到gitcode上的工程hatchCode,大家有兴趣的可以点star进行关注。

结尾

非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/577983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

路由器常见故障分析及处理方法!

对当前的大多数网络来说&#xff0c;无论是实现网络互连还是访问Internet&#xff0c;路由器是不可或缺的。 由于路由器的重要性&#xff0c;对它的管理就成了维护人员的日常工作中重要的一部分&#xff0c;而路由器的故障分析和排除也是令许多维护人员极为困扰的问题之一。 路…

jenkins Job华为云EIP变更带宽

引言: 在数字化时代&#xff0c;云服务资源的弹性管理是企业降低运营成本、提高效率的关键手段。通过弹性公网IP&#xff08;EIP&#xff09;服务&#xff0c;企业可以实现按需计费&#xff0c;优化网络支出。然而&#xff0c;根据业务流量的不同阶段调整计费模式&#xff0c;…

批量归一化

目录 一、BN层介绍 1、深层神经网络存在的问题 2、批量归一化的解决方案 3、BN层作用位置 4、BN层在做什么 5、总结 二、批量归一化从零实现 1、实现批量归一化操作 2、创建BN层 3、对LeNet加入批量归一化 4、开始训练 三、简明实现 1、对LeNet加入批量归一化 2…

Latex如何转成Word

将 LaTeX 文档转换成 Word 文档有几种方法&#xff0c;每种方法都有其优缺点。下面是一些常用的方法&#xff1a; 1. Pandoc Pandoc 是一个文档转换工具&#xff0c;可以将 LaTeX 转换成多种格式&#xff0c;包括 Word。 安装 Pandoc。使用以下命令转换 LaTeX 文件到 Word&a…

【性能优化】EFCore性能优化(一)-IEnumerable和IQueryable

阅读本文你的收获 了解EF Core在使用上应该要注意的地方学习EF Core的优化技术&#xff0c;如禁用跟踪、IQueryable接口等 一、问题描述 Entity Framework Core&#xff08;以下简称EF&#xff09;是微软自家出品的大型O/RM框架&#xff0c;使用EF Core&#xff0c;我们可以在…

【SD】IP-Adapter 进阶 - 垫图 【画风重绘-必看】

目录 关于SD1.5的画风迁移 修改动作-方法一&#xff1a;提示词 修改动作-方法二&#xff1a;openpose 关于SD1.5的画风迁移 1.5测试模型&#xff1a;flat2DAnimerge_v30_2.safetensors [b2c93e7a89] 测试图&#xff1a; 文生图&#xff1a;best quality,masterpiece, co…

20231225在WIN10下使用SSH连接Ubuntu20.04.6

20231225在WIN10下使用SSH连接Ubuntu20.04.6 2023/12/25 23:03 https://jingyan.baidu.com/article/5552ef479e1856108ffbc9e3.html Win10怎么开启SSH功能 Win10怎么开启SSH功能,下面就一起来看看吧! 工具/原料 华硕天选4 Windows10 方法/步骤 点击左下角的开始菜单,打开Wind…

Redis过期删除策略和内存淘汰策略

1、设置Redis键过期时间 Redis提供了四个命令来设置过期时间&#xff08;生存时间&#xff09;。 EXPIRE <key> <ttl> &#xff1a;表示将键 key 的生存时间设置为 ttl 秒。 PEXPIRE <key> <ttl> &#xff1a;表示将键 key 的生存时间设置为 ttl 毫秒。…

flutter怎么对ReorderableListView中的用于排序的控制手柄进行显示或隐藏

我在使用ReorderableListView创建可排序列表的时候&#xff0c;需要在编辑的时候才显示右侧的控制排序的手柄。研究了半天&#xff0c;配合搜索引擎&#xff0c;才找到正确的方案。 答案很简单&#xff0c;就是在它的属性当中有一个叫做&#xff1a;buildDefaultDragHandles的…

SICP : The Elements of Programming

好的计算机编程语言应具备的三个特性 基础单元表达式&#xff0c;计算机编程语言最最最基础单元&#xff0c;理应具备的表达式组合的能力&#xff0c;能够通过基础单元表达式组合成更复杂的元素抽象的能力&#xff0c;能通过复杂的元素抽象成更高层的单元 基础单元表达式 加 …

计算机硬件 4.2显卡

第二节 显卡 一、基本概念 1.定义&#xff1a;是主机与显示器之间的接口电路&#xff0c;也成为显示适配器&#xff0c;决定显示系统的优劣。 2.作用&#xff1a;处理和存储图形数据&#xff0c;向显示器提供信号、控制显示器显示的重要设备。 3.分类&#xff1a;核芯显卡、…

lvgl 双物理显示器的驱动实现

目录 一、背景 1. 要实现的功能2. lvgl 版本 二、简单粗暴的方式 理论上可以这样实现缺陷&#xff1a; 三、lvgl 自身机制支持 3.1 实现思路3.2 初始化缓冲区和注册显示驱动 3.2.1 复制lv_port_disp → lv_port_disp_23.2.2 修改 lv_port_disp_2 文件3.2.3 在应用层调用显示器…

什么是SLAM中的回环检测,如果没有回环检测会怎样

目录 什么是回环检测 如果没有回环检测 SLAM&#xff08;Simultaneous Localization and Mapping&#xff0c;即同时定位与地图构建&#xff09;是一种使机器人或自动驾驶汽车能够在未知环境中建立地图的同时定位自身位置的技术。回环检测&#xff08;Loop Closure Detectio…

快速入门学习定时任务框架-xxljob

定时任务框架-xxljob 简介 主要用于分布式任务调度&#xff0c;可以将任务调度和执行分布在多个节点上。它提供了一个集中式的管理平台&#xff0c;支持动态添加、修改、删除任务&#xff0c;以及任务的分片执行&#xff0c;确保任务在分布式环境中的高可用性的一个框架 spr…

C语言中函数调用和嵌套

函数是C语言的基本组成元素 函数调用 根据函数在程序中出现的位置有下列三种函数调用方式&#xff1a; 将函数作为表达式调用 将函数作为表达式调用时&#xff0c;函数的返回值参与表达式的运算&#xff0c;此时要求函数必须有返回值 int retmax(100,150); 将函数作为语句…

k8s学习 — (DevOps实践)第十四章 微服务 DevOps 实战 【Kubesphere DevOps】

k8s学习 — &#xff08;DevOps实践&#xff09;第十四章 微服务 DevOps 实战 【Kubesphere DevOps】 1 开启 DevOps2 集成 SonarQube3 更新 settings.xml4 部署项目4.1 Spring Boot 项目4.1.1 项目4.1.2 配置文件 4.2 微服务项目4.2.1 项目4.2.2 配置文件 5 DevOps 项目5.1 Sp…

大数据Doris(四十一):物化视图简单介绍

文章目录 物化视图简单介绍 一、适用场景

Windows系统配置pytorch环境,Jupyter notebook编辑器安装使用(深度学习本地篇)

如今现在好一点的笔记本都自带英伟达独立显卡&#xff0c;对于一些简单的深度学习项目&#xff0c;是不需要连接服务器的&#xff0c;甚至数据量不大的话&#xff0c;cpu也足够进行训练学习。我把电脑上一些以前的笔记整理一下&#xff0c;记录起来&#xff0c;方便自己35岁事业…

在Android中使用Flow获取网络连接信息

在Android中使用Flow获取网络连接信息 如果你是一名Android开发者&#xff0c;你可能会对这个主题感到有趣。考虑到几乎每个应用程序都需要数据交换&#xff0c;例如刷新动态或上传/下载内容。而互联网连接对此至关重要。但是&#xff0c;当用户的设备离线时&#xff0c;数据如…

Python之__enter__和__exit__

1. 概述 这两个函数与with as语句语句紧密相连&#xff0c;即 class Test():def __enter__(self):print("Enter!")passdef __exit__(self, type, value, trace):print("Exit!")passwith Test() as f: # 执行with as语句时&#xff0c;Test类中的_…