线程的理解及基本操作

news2024/11/28 20:34:41

目录

一、线程的理解

(1)什么是线程呢?

(2)线程的优缺点及异常

二、线程的基本操作

(1)创建一个新的进程

    (2)获取线程id

(3)线程终止

(4)取消一个线程

(5)线程等待

(6)线程分离

三、gettid和pthread_self的区别


一、线程的理解

(1)什么是线程呢?

        在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列/一个执行流”,一切进程至少都有一个执行线程。
        线程在进程内部运行,本质是在进程地址空间内运行
        在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化
        透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流。

        从这张图中我们可以看到,Linux中其实是没有真正的线程的。Linux中的线程是对进程代码的复用,即在内核中复用进程pcb,作为线程的pcb(tcb),然后让这些pcb都指向一段相同的地址空间,再通过线程库的封装,给用户层营造了操作系统中的线程。

(2)线程的优缺点及异常

优点

缺点

异常

        单个线程如果出现除零,野指针问题导致线程崩溃,进程也会随着崩溃。
        线程是进程的执行分支,线程出异常,就类似进程出异常,进而触发信号机制,终止进程,进程终止,该进程内的所有线程也就随即退出。

(3)线程和进程的一些差别

        1.进程是资源分配的基本单位
        2.线程是调度的基本单位
        3.线程共享进程数据,但也拥有自己的一部分数据:
                线程ID,一组寄存器,栈,errno,信号屏蔽字,调度优先级

        进程的多个线程共享 同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

二、线程的基本操作

(1)创建一个新的进程

参数
        thread:返回线程ID
        attr:设置线程的属性,attr为NULL表示使用默认属性
        start_routine:是个函数地址,线程启动后要执行的函数
        arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码

    (2)获取线程id

        pthread_ create函数会产生一个线程ID,存放在第一个参数指向的地址中。该线程ID和前面说的线程ID不是一回事。
        前面讲的线程ID属于进程调度的范畴。因为线程是轻量级进程,是操作系统调度器的最小单位,所以需要一个数值来唯一表示该线程。
        pthread_ create函数第一个参数指向一个虚拟内存单元,该内存单元的地址即为新创建线程的线程ID,属于NPTL线程库的范畴。线程库的后续操作,就是根据该线程ID来操作线程的。
线程库NPTL提供了pthread_ self函数,可以获得线程自身的ID:

        从这里的结果可以看到这个线程id是一个非常大的数,和我们之前所说的进程id完全不一样,进程id是操作系统中维护的一个id,二线程id是线程库维护的一个id,这个id其实就是该线程描述结构体在地址空间中的起始地址。

        pthread_t 到底是什么类型呢?取决于实现。对于Linux目前实现的NPTL实现而言,pthread_t类型的线程ID,本质就是一个进程地址空间上的一个地址。

        我们知道一个动态库被使用的时候需要被加载到进程地址空间的共享区中,pthread动态库也不例外。在创建一个新的线程的时候,操作系统首先会创建一个pcb结构体来描述该线程(这是内核中的描述结构体),但是对于用户而言,不能直接访问操作系统的内容,于是有了pthread这个软件层封装了操作系统的轻量级进程,给用户看到的直接就是线程。

        而在pthread动态库中,他会维护一个类似于数组的结构,这个数组里面保存了所有线程的描述结构体tcb,里面包含了该线程的属性字段,而pthread_self函数返回的就是该描述结构体的地址!不同于操作系统内核的pid,当然这个描述结构体中一定保存了内核的pid来实现用户层和内核层的转换。

  

(3)线程终止

        线程终止的函数就好像return一样使用,只不过要注意的是,return要返回一个void*的类型,因为我们在pthread_create的时候,他的返回值就是void*类型。

        需要注意的是,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。


        

(4)取消一个线程

        既然能够创建一个线程,那么必然也能取消(销毁)一个线程,这个函数无论是主线程还是其他线程都可以调用,只需要传递该线程的pthread_t参数即可。

(5)线程等待

        和进程等待一模一样,线程也需要被回收。因为Linux中的线程就是复用了进程的代码,也会产生pcb和库中的tcb,一旦没有回收,会造成内存泄漏的问题。

        值得注意的是:这里的第二个参数是一个void**类型,是一个输入输出型参数。因为pthread_create的返回值是void*类型,要想对一个void*类型进行修改需要的参数是void**类型的指针。

        调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,代码如下:

1. 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值。
2. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数PTHREAD_ CANCELED。
3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
4. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数。

5.线程的返回结果是由线程库来维护的,想要获取返回信息必须要用pthread_join函数。如果线程是分离的,则线程库不会维护其返回值,其他线程也无法通过线程库来获取其返回信息

(6)线程分离

        默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。
        如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。

        一旦线程分离了,主线程再等待,返回值就不再是0

        该函数可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离。与线程终止函数使用无差。joinable和分离是冲突的,一个线程不能既是joinable又是分离的。

三、gettid和pthread_self的区别

        简单来说:gettid返回的是内核存储pcb的pid;而pthread_self返回的是线程库中的id(也就是描述结构体tcb的起始地址)。

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

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

相关文章

H3C OSPF配置

OSPF配置实验 实验拓扑图 实验需求 1.配置IP地址 2.分区域配置OSPF&#xff0c;实现全网互通 3.为了路由结构稳定&#xff0c;要求路由器使用环回口作为Router-id&#xff0c;ABR的环回口宣告进骨干区域 实验配置 1.配置IP地址 R1&#xff1a; <H3C>system-view …

apt的编译安装(古老通讯)

Ubuntu系统的防火墙关闭&#xff1a; ufw disable 第一步&#xff1a;Ubuntu 安装依赖环境 apt -y install libpcre3-dev zlib1g-dev libssl-dev build-essential 如果出现无法下载则在末尾处假如 --fix missing如下图所示 出现下图则为安装成功 第二步&#xff1a; useradd…

Vue.js(2) 入门指南:从基础知识到核心功能

我相信一万小时定律&#xff0c;不相信天上掉馅饼的灵感和坐等的成就。做一个自由而自律的人&#xff0c;势必靠决心认真地活着 文章目录 前言vue是什么?vue做什么?vue的核心功能安装vuevue初体验vue配置选项插值表达式指令vue阻止默认行为总结 前言 Vue.js 是一个用于构建用…

Spring 启动流程分析

Spring 的设计 Bean: Spring作为一个IoC容器&#xff0c;最重要的当然是Bean咯 BeanFactory: 生产与管理Bean的工厂 BeanDefinition: Bean的定义&#xff0c;也就是我们方案中的Class&#xff0c;Spring对它进行了封装 BeanDefinitionRegistry: 类似于Bean与BeanFactory的关…

智能名片小程序源码

智能名片小程序&#xff0c;是一款集在线介绍公司和个人名片、高效获取客户信息以及全面展示公司产品于一体的数字化工具。它通过数字化的方式&#xff0c;让名片信息的传递更加高效、便捷&#xff0c;极大地提升了商务交流的效率和效果。 在功能性方面&#xff0c;智能名片小…

LabVIEW汽车状态监测系统

LabVIEW汽车状态监测系统通过模拟车辆运行状态&#xff0c;有效地辅助工程师进行故障预测和维护计划优化&#xff0c;从而提高汽车的可靠性和安全性。 项目背景&#xff1a; 现代汽车工业面临着日益增长的安全要求和客户对于车辆性能的高期望。汽车状态监测系统旨在实时监控汽…

Golang的Web应用架构设计

# Golang的Web应用架构设计 介绍 是一种快速、高效、可靠的编程语言&#xff0c;它在Web应用开发中越来越受欢迎。Golang的Web应用架构设计通常包括前端、后端和数据库三个部分。在本篇文章中&#xff0c;我们将详细介绍Golang的Web应用架构设计及其组成部分。 前端 在Golang的…

SIP 业务举例之 三方通话:邀请第三方加入的信令流程

目录 1. 3-Way Conference - Third Party Is Added 简介 2. RFC5359 的 3-Way Conference - Third Party Is Added 信令流程 3. 3-Way Conference - Third Party Is Added 总结 博主wx:yuanlai45_csdn 博主qq:2777137742 想要 深入学习 5GC IMS 等通信知识(加入 51学通信)…

GNN+强化学习:双霸主强强联合,10种创新思路刷爆顶会!

图神经网络&#xff08;GNN&#xff09;强化学习&#xff08;RL&#xff09;&#xff0c;融合了GNN在图数据表示上的深度学习能力和RL在决策过程中的策略优化能力。这种结合为处理具有复杂图结构的数据问题提供了强大的工具。 GNN与强化学习的结合不仅推动了图机器学习的研究进…

R语言机器学习算法实战系列(十三)随机森林生存分析构建预后模型 (Random Survival Forest)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍教程加载R包案例数据数据预处理数据描述构建randomForestSRC模型评估模型C-indexBrier score特征重要性构建新的随机森林生存模型风险打分高低风险分组的生存分析时间依赖的ROC(Ti…

Http 状态码 301 Permanent Rediret 302 Temporary Redirect、 重定向 重写

HTTP状态码301和302是什么&#xff1f; 1、HTTP状态码301 HTTP状态码301表示永久性转移&#xff08;Permanent Redirect&#xff09;&#xff0c;这意味着请求的资源已经被分配了一个新的URI&#xff0c;以后的引用应该使用资源现在所指的URI。 HTTP 301状态码表示请求的资源…

Segugio:一款针对恶意软件的进程执行跟踪与安全分析工具

关于Segugio Segugio是一款功能强大的恶意软件安全分析工具&#xff0c;该工具允许我们轻松分析恶意软件执行的关键步骤&#xff0c;并对其进行跟踪分析和安全审计。 Segugio允许执行和跟踪恶意软件感染过程中的关键步骤&#xff0c;其中包括从点击第一阶段到提取恶意软件的最…

CSS.导入方式

1.内部样式 在head的style里面定义如 <style>p1{color: brown;}</style> 2.内联样式 直接在标签的里面定义如 <p2 style"color: blue;">这是用了内联样式&#xff0c;蓝色</p2><br> 3.外部样式表 在css文件夹里面构建一个css文件…

Java Lock CyclicBarrier 总结

前言 相关系列 《Java & Lock & 目录》&#xff08;持续更新&#xff09;《Java & Lock & CyclicBarrier & 源码》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Java & Lock & CyclicBarrier & 总结》&#xff08;学习总结…

【现代C++】常量求值

现代C&#xff08;特别是C11及以后的版本&#xff09;增强了对编译时常量求值的支持&#xff0c;包括constexpr函数、constinit和consteval关键字。这些特性允许在编译时进行更多的计算&#xff0c;有助于优化运行时性能并确保编译时的数据不变性。 1. constexpr - 编译时常量…

[含文档+PPT+源码等]精品基于PHP实现的培训机构信息管理系统的设计与实现

基于PHP实现的培训机构信息管理系统的设计与实现背景&#xff0c;可以从以下几个方面进行阐述&#xff1a; 一、社会发展与教育需求 随着经济的不断发展和人口数量的增加&#xff0c;教育培训行业迎来了前所未有的发展机遇。家长对子女教育的重视程度日益提高&#xff0c;课外…

雷池社区版compose配置文件解析-mgt

在现代网络安全中&#xff0c;选择合适的 Web 应用防火墙至关重要。雷池&#xff08;SafeLine&#xff09;社区版免费切好用。为网站提供全面的保护&#xff0c;帮助网站抵御各种网络攻击。 compose.yml 文件是 Docker Compose 的核心文件&#xff0c;用于定义和管理多个 Dock…

LeetCode题(二分查找,C++实现)

LeetCode题&#xff08;二分查找&#xff0c;C实现&#xff09; 记录一下做题过程&#xff0c;肯定会有比我的更好的实现办法&#xff0c;这里只是一个参考&#xff0c;能帮到大家就再好不过了。 目录 LeetCode题&#xff08;二分查找&#xff0c;C实现&#xff09; 一、搜…

Rust编程与项目实战-元组

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust编程与项目实战_夏天又到了的博客-CSDN博客 8.2.1 元组的定义 元组是Rust的内置复合数据类型。Rust支持元组&#xff0c;而且元…

腾讯云跨AZ部署FortigateHA备忘录

随时保存配置 config system globalset admintimeout 480set alias "FortiGate-VM64-KVM"set gui-auto-upgrade-setup-warning disableset hostname "FG-Slave"set revision-backup-on-logout enableset revision-image-auto-backup enableset timezone &…