Linux线程:创建(pthread_create),等待(pthread_join),退出(pthread_exit)

2023-10-29

目录

一 线程说明

①线程与进程:

②线程优点:

③线程缺点:

二 线程开发API概要

三 线程控制流程

① 线程创建(pthread_create)

② 线程退出(pthread_exit)

③ 线程等待(pthread_join)

④ 线程脱离(pthread_detach)

⑤ 线程ID获取(pthread_self)

四 完整代码示例


一 线程说明

Linux 实现线程的机制非常独特。从内核的角度来说,它并没有线程这个概念。 Linux 把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构来表示线程。线程只被视为一个与其他进程共享某些资源的轻量级进程。所以在内核中,它看起来就像是一个普通的进程(只是线程和其他一些进程共享某些资源,如地址空间)
 

①线程与进程:

①所有的轻量级进程(线程)都是在进程的内部运行;

进程是资源分配的最小单位,线程是程序执行的最小单位;

③进程具有独立性,可以有部分共享资源(比如:管道,IPC资源);

④线程大部分资源是共享的(例如:代码、进程数据、文件描述符、信号处理方式),可以有部分资源是私有的(例如:PCB、栈、上下文);

★ 每个线程是有自己的独立栈,保存线程运行时形成的临时数据;上下文中保存的是CPU调度时存放在寄存器中的临时数据。

线程 进程
标识符类型 pthread_t pid_t
获取id pthread_self() getpid()
创建 pthread_create() fork()


 

②线程优点:

① 创建一个新线程的代价要比创建一个新进程小得多;

② 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多;

③ 线程占用的资源要比进程少很多;

④ 能充分利用多处理器的可并行数量;

⑥ 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务;

⑦ 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现;

⑧ I/O密集型应用,为了提高性能,将I/O等待就绪操作重叠。线程可以同时等待不同的I/O操作;
 

③线程缺点:

性能损失:一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型 线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的 同步和调度开销,而可用的资源不变;

健壮性降低:编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了 不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的;

缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响;

④ 编程难度提高:编写与调试一个多线程程序比单线程程序困难得多。

二 线程开发API概要

多线程开发在 Linux 平台上已经有成熟的 pthread 库支持。其涉及的多线程开发的最基本概念主要包含三点:线程,互斥锁,条件。其中,线程操作又分线程的创建,退出,等待 3 种。互斥锁则包括 4 种操作,分别是创建,销毁,加锁和解锁。条件操作有 5 种操作:创建,销毁,触发,广播和等待。其他的一些线程扩展概念,如信号灯等,都可以通过上面的三个基本元素的基本操作封装出来。详细请见下表:

三 线程控制流程

本篇文章先说明线程的创建,等待,退出这三个API;

  • 使用-pthread编译和链接。

① 线程创建(pthread_create)

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

//返回值:成功返回0,失败返回错误编号

pthread_t *thread:线程ID,由函数pthread_self()获取,类似获取进程pid使用getpid()函数;

const pthread_attr_t *attr:用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程;

void *(*start_routine) (void *):线程中执行函数。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg

void *arg:执行函数中中参数。如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构体中,然后把这个结构的地址作为arg参数传入

② 线程退出(pthread_exit)

单个线程可以通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流:

 1)线程只是从启动例程中返回,返回值是线程的退出码。

 2)线程可以被同一进程中的其他线程取消。

 3)线程调用pthread_exit:

#include <pthread.h>
int pthread_exit(void *rval_ptr);

rval_ptr:是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。

③ 线程等待(pthread_join)

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号

调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果例程只是从它的启动例程返回,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。①可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。②如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。

④ 线程脱离(pthread_detach)

一个线程或者是可汇合(joinable,默认值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join。脱离的线程却像守护进程,当它们终止时,所有相关的资源都被释放,我们不能等待它们终止。如果一个线程需要知道另一线程什么时候终止,那就最好保持第二个线程的可汇合状态。

pthread_detach函数把指定的线程转变为脱离状态

#include <pthread.h>
int pthread_detach(pthread_t thread);
// 返回:若成功返回0,否则返回错误编号

 本函数通常由想让自己脱离的线程使用,就如以下语句:

pthread_detach(pthread_self());

⑤ 线程ID获取(pthread_self)

#include <pthread.h>
pthread_t pthread_self(void);
// 返回:调用线程的ID

四 完整代码示例

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void *func(void *arg)//定义执行函数func
{
        static int ret = 10;//定义tid2线程退出码
        printf("tid2:%lu\n",pthread_self());//
        printf("pid2:%d\n",getpid());//进程id
        pthread_exit((void *)&ret);//结束线程tid2
}
int main()
{
        int *pret;
        pthread_t tid1;//定义主线程
        pthread_t tid2;//定义子线程
        pid_t pid1;//进程id
        pid_t pid2;//进程id
        printf("tid1:%lu\n",pthread_self());//打印主线程id
        printf("pid1:%d\n",getpid());//打印进程id
        pthread_create(&tid2,NULL,func,NULL);//创建线程tid2
        pthread_join(tid2,(void **)&pret);//等待线程tid2退出,获取退出状态码
        printf("tid2 exit retval:%d\n",*pret);//打印线程退出的状态码
        return 0;
}

代码执行结果:进程id一样,线程id不一样,说明在同一个进程中执行了两条不同的线程,获取到已经定义好的退出状态码10。

dhw@dhw-virtual-machine:~/thread$ ./a.out
tid1:140212273063744
pid1:6791
tid2:140212273059392
pid2:6791
tid2 exit retval:10

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux线程:创建(pthread_create),等待(pthread_join),退出(pthread_exit) 的相关文章

  • 怎样才能使 Windows 成为一个开箱即用的 POSIX 兼容操作系统?

    这个问题的动机是我的一个牵强的梦想 即 nix 平台上可用的许多优秀软件可以轻松移植到 Windows 微软最近对开源和开放性采取了不同的方法 所以我真的很想知道如果微软有这样的倾向 这样的事情会有多可行 我很好奇的一些更具体的事情是 是否
  • 如何在我的 AWS EC2 实例上安装特定字体?

    我有一个在 AWS EC2 Amazon Linux Elastic Beanstalk 实例上运行的 Python 应用程序 该实例需要某些特定字体才能生成输出 并且想知道如何在部署或实例启动过程中安装它们 我的代码在本地计算机 OS X
  • InstaPy:“错误,无法确定 64 位 Linux 的正确文件名”

    有人知道如何解决或解决这个问题吗 来自控制台的堆栈跟踪 执行后报告错误 InstaPy Version 0 6 9 Workspace in use home zanettra InstaPy Error unable to determi
  • 如何不断刷新屏幕并实时更新[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想在linux上写一个C程序 不断刷新屏幕并实时更新 例如类似于top终端中的命令 谁能指出我正确的方向 为了保持它跨终端类型的可移
  • 在Linux中断上下文中运行用户线程

    我正在编写一些定制的应用程序 并允许更改 Linux 内核中的中断处理程序代码 我有一个用户线程正在等待中断发生 如果发生中断 那么我要做的第一件事就是执行该用户线程 有什么办法让它发挥作用吗 Thanks 创建一个字符设备 这就是内核所做
  • 在 Ubuntu 16.04 上找不到 printf.c

    我最近切换到Ubuntu 16 04 我在用vscode作为 Ubuntu 上的 IDE 我配置了其他语言 但我无法做到这一点C C 我创建c cpp properties json launch json tasks json 当我开始编
  • linux x86 汇编语言 sys_read 调用的第一个参数应为 0 (stdin)

    我正在编写一个简单的汇编程序来从标准输入读取 如 scanf 这是我的代码 section bss num resb 5 section txt global start start mov eax 3 sys read mov ebx 0
  • Vim 函数插入带有传递参数的静态文本

    背景 I m interested in writing a function that assigned to keyboard shortcut s when invoked would 采取用户参数 计算值反映80 string le
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • VIM 始终使用选项卡式页面

    我想要一个可以放入 vimrc 文件中的命令 该命令将使 vim 始终以选项卡式页面模式打开 而无需传递 p在命令行上 有这样的命令吗 如果没有 是否有更好的方法来做到这一点 目前 我正在使用 alias vi vim p 在我的 bash
  • 在Vim函数中获取不带文件扩展名的文件名

    我想在Vim中获取不带文件扩展名的文件名 我在我的中编写了以下函数 vimrc文件来编译并运行Java程序 function JAVA RUN javac M endfunction map
  • 使 'n' 始终向前搜索,无论是否 / 或 ?用于搜索

    我几乎总是在 Vim 中搜索 然后继续向前搜索n并向后N 然而 有时我会使用 跳转到我当前所在行上方几行的项目 在这种情况下 如果我想向前搜索同一项目 我必须使用N代替n 令人烦恼的心理减速带 所以我的问题是 是否有可能使n永远向前走 并且
  • .NET Core 中的跨平台文件名处理

    如何处理文件名System IO以跨平台方式运行类以使其在 Windows 和 Linux 上运行 例如 我编写的代码在 Windows 上完美运行 但它不会在 Ubuntu Linux 上创建文件 var tempFilename Dat
  • 在 Linux 中禁用历史记录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 要在 Linux 环境中禁用历史记录 我执行了以下命令 export HISTFILESIZE 0 export HISTSIZE 0 u
  • Godaddy 托管上的 CakePHP 控制台

    我一直在努力让我的 CakePHP 网站在 Godaddy 网格托管 帐户上运行 我的蛋糕应用程序设置是从帐户的子目录托管的 并且可以通过子域访问 我必须调整我的 htaccess 文件才能使其正常工作 现在我需要让 CakePHP 控制台
  • Locale.getDefault() 始终返回 en

    unix 机器上的服务器始终使用 en 作为默认区域设置 以下是区域设置输出 LANG en US LC CTYPE C LC NUMERIC C LC TIME C LC COLLATE C LC MONETARY C LC MESSAG
  • 如何修复“iptables:没有该名称的链/目标/匹配”?

    我在我的 Linux 嵌入式系统上构建并安装了 iptables 如果我列出所有规则 则一切正常 iptables list Chain INPUT policy ACCEPT target prot opt source destinat
  • 为什么我收到“无法进行二进制日志记录”的信息。在我的 MySQL 服务器上?

    当我今天启动 MySQL 服务器并尝试使用以下命令进行一些更改时用于 MySQL 的 Toad http www quest com toad for mysql 我收到此消息 MySQL 数据库错误 无法进行二进制日志记录 消息 交易级别
  • Android:ANT 构建失败,并显示 google-play-services-lib:“解析为没有项目的 project.properties 文件的路径”

    我正在尝试使用 ANT 构建我的应用程序 但在包含 google play services lib 库项目后 我惨遭失败 Step 1 我在 project properties 文件中设置了对库项目的引用 android library
  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案

随机推荐

  • Windows下配置环境变量

    Windows下配置环境变量 在安装某些软件或者应用程序时 需要配置环境变量 以便在后续可以正常使用 环境变量相当于给系统或用户应用程序设置一些参数 具体起什么作用和对应的环境变量相关 比如path 是告诉系统 当要求系统运行一个程序而没有
  • React 18的新特新

    React 18 最新的特性 批处理文件 在同一个 函数中 调用多次 useState 也只是会更新一次 function App const count setCount useState 0 const flag setFlag use
  • 基于51单片机的水位液位温度监测鱼缸系统仿真原理图程序

    硬件设计 上一篇咱们讲了基于数码管显示的液位检测 本章讲一下基于LCD1602显示的液位检测 同时伴有温度测量 该系统可应用于鱼缸 水塔 水箱的检测 本系统液位检测方案是基于液位传感器 通过传感器嵌入液体反馈回电信号 通过电信号的大小可以反
  • 如何利用python将一个list中的数字提取,然后求和?

    coding UTF 8 import re name score list u 唐僧 100 u 猪八戒 60 u 孙悟空 95 u 沙和尚 80 1 将score list列表转换为以 为分隔符的字符串 name score list
  • 极限学习机ELM原理与实现

    极限学习机 ELM 是当前一类非常热门的机器学习算法 被用来训练单隐层前馈神经网络 SLFN 本篇博文尽量通俗易懂地对极限学习机的原理进行详细介绍 之后分析如何用python实现该算法并对代码进行解释 1 算法的原理 极限学习机 ELM 用
  • 【STM32】 JDY-31蓝牙模块

    目录 一 介绍 二 模块特点 三 产品应用范围 四 模块技术参数 五 模块接口说明 六 蓝牙模块接口电路图 七 蓝牙模块实物图 一 介绍 蓝牙模块是指集成蓝牙功能的芯片基本电路集合 用于无线网络通讯 本蓝牙模块就是为了只能无线数据传输而专门
  • 微服务 - 拆分微服务的问题和拆分方法

    概述 现在被谈论最多的就是微服务和中台系统 我个人的理解是微服务或者是中台好不好 主要看实际的业务场景 架构的变迁往往需要耗费很大的学习成本和时间成本 所以更改架构的时候要三思而后行 适合自己特别重要 由单体到多应用的演变 从我入职开始 公
  • 变压器哪些部位易造成渗油?

    变压器哪些部位易造成渗油 答 1 套管升高座电流互感器小绝缘子引出线的桩头处 所有套管引线桩头 法兰处 2 气体继电器及连接管道处 3 潜油泵接线盒 观察窗 连接法兰 连接螺丝紧固件 胶垫 4 冷却器散热管 5 全部连接通路碟阀 6 集中净
  • [前端] vue开发的项目用ajax发送请求携带cookie

    只需要在main js中写这三行代码即可 import axios from axios axios defaults withCredentials true 让ajax携带cookie Vue prototype axios axios
  • 初谈 ChatGPT

    引子 最近 小编发现互联网中的大 V 突然都在用 ChatGPT 做宣传 ChatGPT不会淘汰你 能驾驭ChatGPT的人会淘汰你 带领一小部分人先驾驭ChatGPT 确实 ChatGPT这个新生事物 如今被视为蒸汽机 电脑 iPhone
  • 众所周知,YouTube是个学习网站

    大数据文摘出品 来源 medium 编译 Hippo 国内有小破站 国外有YouTube 就像国内的b站一样 YouTube不仅是一个多媒体娱乐帝国 还是一个全面的学习平台 每月无需支付订阅费即可在YouTube上观看视频 所有供你观看和学
  • dev GridControl 按条件纵向合并单元格

    dev GridControl 按条件纵向合并单元格 gridView5 OptionsView AllowCellMerge true gridView5 CellMerge gridView5 CellMerge 自定义合并单元格监听事
  • npm安装报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree

    项目场景 安装npm报错npm ERR code ERESOLVE npm ERR ERESOLVE unable to resolve dependency tree 原因分析 ERESOLVE与npm 7 x的问题 7 x有些处理检测比
  • 黑马JVM总结(十五)

    1 GC 相关参数 2 GC 分析1 下面通过一个案例去读懂垃圾回收的一个过程 学会读懂垃圾回收的日志 XX UseSerialGC 是一个垃圾回收器 jdk8下默认的垃圾回收器不是它 改为UseSerialGC它的幸存区的比例才不会调整
  • Jenkins系列(五)----Jenkins自动发布spring-boot应用

    一 测试环境 三台服务器来测试 一台SVN服务器 一台Jenkins服务器 一台应用服务器 如下 Jenkins服务器 192 168 84 100 SVN服务器 192 168 84 105 应用服务器 192 168 84 101 二
  • 第二篇:Spring Boot整合JPA、事务处理及AOP的使用

    一 Spring Boot整合JPA的具体步骤 注 Spring Boot整合JPA 源码下载 注 springboot学习资料汇总 参考 spring data jpa的使用 参考 Spring Cloud微服务实战 作者 参考 方志朋博
  • SQLyog软件里无法插入中文(即由默认的latin1改成UTF8编码格式)

    问题详情 无法插入中文 解决办法 需要修改编码格式 由默认的latin1改为utf8 改成 成功
  • ZZULIOJ 2829: 闯关游戏 (DP)

    2829 闯关游戏http acm zzuli edu cn problem php id 2829 include
  • 计算机专业名称bios翻译,bios英文翻译 最全BIOS设置中英文对照表

    对于熟悉电脑的人来说 设置BIOS是一件非常简单的事情 但对于小白来说 别说设置BIOS了 看不看得懂这些乱七八糟的英文都很难说 为了熟悉重装系统的教程 有写用户会在虚拟机上去尝试 今天小编就为你们翻译出BIOS的英文 不懂英文的小伙伴们赶
  • Linux线程:创建(pthread_create),等待(pthread_join),退出(pthread_exit)

    目录 一 线程说明 线程与进程 线程优点 线程缺点 二 线程开发API概要 三 线程控制流程 线程创建 pthread create 线程退出 pthread exit 线程等待 pthread join 线程脱离 pthread deta