15-2-线程-线程的创建,等待,退出

news2024/10/5 19:17:57

一、相关API

1. 线程创建

1. 线程创建
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);


参数:
  参数1:(创建的线程 的地址)当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。
    参数2:(配置为NULL时,指创建默认属性的线程)attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
    参数3:(线程调用的函数)新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。
    参数4:(传给“线程调用的函数”的参数)如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,
然后把这个结构的地址作为arg参数传入。

返回值:
若成功返回0,
否则返回错误编号

 实验:

(1)创建线程,向线程传递1个参数,线程调用函数,该函数把传递给线程的参数打印出来。

描述:

如图,编写了以下代码;并且编译时连接了libpthread.a库;

ret = pthread_create(&t1,NULL,fun1,(void *)&param);

参数一:&t1

参数二:NULL,表示新建的线程的属性为默认属性;

参数三:fun1,函数指针,该函数是新建的线程所要执行的函数,该函数只能有1个参数,如果想要传递多个参数则需要依赖结构体。

参数四:(void *)& param,是传递给fun1函数的实参;(注意:首先要把参数强制转换为指针类型,因为fun1函数的形参和返回值的类型都必须为 void 类型。void 类型又称空指针类型,表明指针所指数据的类型是未知的。使用此类型指针时,我们通常需要先对其进行强制类型转换,然后才能正常访问指针指向的数据。)fun1读取该参数时,先把arg转换为intx型指针(int *(arg)),再读取*(int *(arg));

程序中为什么加while(1); ?

答:程序运行时,不加”while(1);”时,主进程判断ret!=0会直接退出,fun1()还没执行完时主进程就退出了。

#include <stdio.h>
#include <pthread.h>


void *fun1(void *arg)
{

        printf("%ld thread is created\n",(unsigned long)pthread_self());
        printf("param = %d\n",*((int *)arg));


}



int main()
{
        int ret;
        int param = 100;
        pthread_t t1;

        int *pret = NULL;

        ret = pthread_create(&t1,NULL,fun1,(void *)&param);
        if(ret == 0)
        {
                printf("creat t1 success\n");
        }

        while(1);
        return 0;
}

运行结果:

 (2)创建线程,向线程传递多个参数(这些参数都放在1个结构体里面),线程调用函数,该函数把传递给线程的参数打印出来。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
struct STU1{
        char name[128];
        int param1;
        int param2;
};
void *fun1(void *arg)
{

        printf("%ld thread is created\n",(unsigned long)pthread_self());
        printf("&Sparam %d\n",arg);
        struct STU1 *p1;
        p1 = (struct STU1 *)arg;
        printf("arg->name::%s\n",p1->name);
        printf("arg->param1::%d\n",p1->param1);
        printf("arg->param2::%d\n",p1->param2);


}



int main()
{
        int ret;

        pthread_t t1;

        int *pret = NULL;
        struct STU1 Sparam = {"yrx0203",100,88};
        struct STU1 *p;
        p = (struct STU1 *)malloc(sizeof(struct STU1) );
        p = &Sparam;

        ret = pthread_create(&t1,NULL,fun1,(void *)p);
        if(ret == 0)
        {
                printf("creat t1 success\n");
        }

        while(1);
        return 0;
}

 运行结果如图:

 

2.线程等待与退出

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);

参数1:线程的名称
参数2:如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。
       如果对线程的返回值感兴趣,则把参数二设置为void型的二级指针。(这个二级指针传递给线程后,在线程退出时, int pthread_exit(void *rval_ptr);会改变这个二级指针的值)

返回值:
若成功返回0,
否则返回错误编号

  调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit从启动例程中返回或者被取消。
如果例程只是从它的启动例程返回,rval_ptr将包含返回码。
如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。

  可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。
#include <stdio.h>
#include <pthread.h>


void *fun1(void *arg)
{
        static ret =10;
        printf("%ld thread is created\n",(unsigned long)pthread_self());
        printf("param = %d\n",*((int *)arg));

        pthread_exit((void *)&ret);
}



int main()
{
        int ret;
        int param = 100;
        pthread_t t1;

        int *pret = NULL;

        ret = pthread_create(&t1,NULL,fun1,(void *)&param);
        if(ret == 0)
        {
                printf("creat t1 success\n");
        }
        pthread_join(t1,(void **)&pret);
        printf("*pret=%d\n",*pret);
        while(1);
        return 0;
}

运行结果:

 

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

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

相关文章

【JavaEE】TCP回写服务器简易翻译服务器(网络编程)

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 上一篇我们讲解了UDP回写服务器和简易翻译服务器&#xff0c;想了解本篇文章&#xff0c;建议先看看上篇文章&#xff0c;学起来会更容易一些~~传送门&#xff1a;(1条消息) 【JavaEE】UDP数…

创新案例|香氛新品牌观夏如何以DTC模式仅4年实现年收过亿

国产香氛品牌观夏的DTC战略&#xff0c;正是从产品创新、全渠道布局、社交电商营销等方面创新&#xff0c;实现更高效地直接触达和转化消费者。观夏作为香氛DTC品牌的创新模式值得更多国内新品牌的关注与借鉴&#xff0c;同时也能为传统品牌的DTC转型提供全球化视野的启示。 1.…

改进YOLOv8: | ICLR 2022 | 涨点神器!Intel提出ODConv:即插即用的动态卷积 | 轻量化涨点创新必备

OMNI-DIMENSIONAL DYNAMIC CONVOLUTION ODConv实验核心代码修改文件yaml文件运行论文链接: https://openreview.net/forum?id=DmpCfq6Mg39 本文介绍了一篇动态卷积的工作:ODConv,其通过并行策略采用多维注意力机制沿核空间的四个维度学习互补性注意力。作为一种“即插即用…

3。数据结构(1)

嵌入式软件开发第三部分&#xff0c;各类常用的数据结构及扩展&#xff0c;良好的数据结构选择是保证程序稳定运行的关键&#xff0c;&#xff08;1&#xff09;部分包括数组&#xff0c;链表&#xff0c;栈&#xff0c;队列。&#xff08;2&#xff09;部分包括树&#xff0c;…

使用rt thread studio新建一个rt thread工程的详细操作说明(以stm32F411CEU6)为例

新建工程 这里以rt thread 5.0以及stm32F411CEU6芯片为例&#xff0c;创建工程 先建一个工作空间 .metadata是建工作空间自己生成的。 这时候&#xff0c;工作空间是空的&#xff0c;没有项目: 新建项目 首先下载RT-thread源文件和芯片支持包&#xff1a; 2023.05.02&#x…

NOIP2000 提高组 方格取数 线性DP 坐标优化 全局最优

&#x1f351; 算法题解专栏 &#x1f351; [NOIP2000 提高组] 方格取数 题目描述 设有 N N N \times N NN 的方格图 ( N ≤ 9 ) (N \le 9) (N≤9)&#xff0c;我们将其中的某些方格中填入正整数&#xff0c;而其他的方格中则放入数字 0 0 0。如下图所示&#xff08;见样…

延时队列的三种实现方案

延时队列的三种实现方案 什么是延时队列延时队列的应用场景基于Java DelayQueue的实现源码剖析 基于Redis的zset实现实现步骤Redis延时队列优势Redis延时队列劣势 基于RabbitMQ的延时队列实现TTL DXL(死信队列)插件实现 总结参考文章 什么是延时队列 在分布式系统中&#xff…

Go(二):包管理、通道、协程并发、互斥锁基础

包管理、协程并发基础 生成包管理文件go-mod第一步&#xff08;初始化创建包管理文件&#xff09;第二步&#xff08;导入包&#xff09; 常用命令导入远程包&#xff08;示例&#xff1a;gin&#xff09;第一步&#xff08;导入包&#xff09;第二步&#xff08;安装包&#x…

操作系统之进程同异步、互斥

引入 异步性是指&#xff0c;各并发执行的进程以各自独立的、不可预知的速度向前推进。 但是在一定的条件之下&#xff0c;需要进程按照一定的顺序去执行相关进程&#xff1a; 举例说明1&#xff1a; 举例说明2: 读进程和写进程并发地运行&#xff0c;由于并发必然导致异步性…

【Python】如何在Python中绘制带有连接线的双饼图?

文章目录 一、导入所需的库二、准备数据三、绘制双饼图3.1 创建画布和子图对象3.2 绘制大饼图3.3 绘制小饼图3.4 连接线1&#xff0c;连接大饼图的上边缘和小饼图的饼块3.5 连接线2&#xff0c;连接大饼图的下边缘和小饼图的饼块3.6 添加连接线3.7 调整子图布局 四、源代码 在 …

Linux 内核组织(kernel.org)将关闭 FTP 服务

Linux 内核组织&#xff08;kernel.org&#xff09;是一家建立于 2002 年的加利福尼亚公共福利公司&#xff0c;其目的是公开地免费分发 Linux 内核和其它开源软件。它接受 Linux 基金会的管理&#xff0c;包括技术、资金和人员支持&#xff0c;用以维护kernel.org 的运营。 Li…

2 ROS2话题通讯基础(1)

2 ROS2话题通讯基础 2.1 ROS2话题通讯介绍2.2 ROS2常用的消息类型介绍2.2.1 std_msgs消息类型2.2.2 geometry_msgs消息类型 2.3 使用C/C创建基础消息类型的话题通讯2.3.1 创建C/C发布话题信息的功能包并配置VSCode环境2.3.2 编写ROS2发布话题节点CPP文件2.3.3 配置C/C发布话题功…

【Elasticsearch】SQL操作相关

文章目录 SQL操作数据准备查询索引下的数据SQL转化为DSL(本质)SQL与DSL混合使用查看所有索引查询指定索引查看索引(表)结构where条件过滤group by分组having 对分组后的数据进行过滤order by 排序limit 限制查询数量cursor 游标->为缓存设计聚合操作支持的函数和运算比较运算…

虚拟机和Docker有什么区别?

虚拟机 对于虚拟机&#xff0c;抽象层或抽象软件成为管理程序。管理程序就是帮助虚拟机模拟物理计算机的东西。在管理程序下面&#xff0c;我们有些硬件。管理程序管理单个物理主机上不同虚拟机之间的资源分配。管理程序管理单个物理主机上不同虚拟机之间的资源分配。也就是管…

微信小程序学习实录3(环境部署、百度地图微信小程序、单击更换图标、弹窗信息、导航、支持腾讯百度高德地图调起)

百度地图微信小程序 一、环境部署1.need to be declared in the requiredPrivateInfos2.api.map.baidu.com 不在以下 request 合法域名3.width and heigth of marker id 9 are required 二、核心代码&#xff08;一&#xff09;逻辑层index.js&#xff08;二&#xff09;渲染层…

vue diff算法与虚拟dom知识整理(2) snabbdom简介并搭建开发环境

snabbdom算是diff算法 和 虚拟dom 的一个鼻租了 vue源码借鉴了snabbdom 这个单词翻译出来叫速度 命名还是用了点心的 后面是 dom 这个 我们大概去猜作者的意思 大概想表示的就是 一个比较快的dom操作 snabbdom的get地址如下 https://github.com/snabbdom/snabbdom 这里的简…

「OceanBase 4.1 体验」|快速安装部署[OBD方式]

文章目录 一、Oceanbase数据库简介1.1 核心特性1.2 系统架构1.2.1 存储层1.2.2 复制层1.2.3 均衡层1.2.4 事务层1.2.4.1 原子性1.2.4.2 隔离性 1.2.5 SQL 层1.2.5.1 SQL 层组件1.2.5.2 多种计划 1.2.6 接入层 二、OceanBase 数据库社区版部署2.1 部署方式2.2 基础环境配置2.3 通…

【华为OD机试真题】信号发射和接收(javaC++python)100%通过率 超详细代码注释 代码深度解读

信号发射和接收 知识点数组栈 单调栈时间限制: 1s 空间限制: 256MB 限定语言:不限 题目描述: 有一个二维的天线矩阵&#xff0c;每根天线可以向其他天线发射信号也能接收其他天线的信号&#xff0c;为了简化起见&#xff0c;我们约定每根天线只能向东和向南发射信号&#xf…

【ROS仿真实战】获取机器人在gazebo位置真值的三种方法(三)

文章目录 前言一. 使用ROS tf库二、 使用Gazebo Model Plugin三、 使用libgazebo_ros_p3d插件四、总结 前言 在ROS和Gazebo中&#xff0c;获取机器人的位置信息通常通过ROS消息传递进行。在这篇文章中&#xff0c;我们将介绍三种获取机器人在Gazebo中位置真值的方法&#xff1…

CTF ASCII码 密码解密题 简单

1. 题目 这次的CTF题目就是一张图片如下&#xff0c;并且说有几个蛋被打乱过。明显是一个密码学的解码题。 2. 解题思路 左边表格给出10种颜色&#xff0c;特别是第二列给出了数字0&#xff0c;种种迹象都指向了10进制。每一个蛋都有三种颜色&#xff0c;代表每个蛋都是三位…