Linux之线程(1)

linux c++实现两个线程轮流打印1~100 思路:使用条件变量,一个线程等待count变成奇数,一个线程等待count变成偶数。 #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> pthread_cond_t cond_odd = PTHREAD_COND_INITIALIZER; ... 阅读详情

今天讲下Linux线程这块的知识,我想很多人应该都知道多线程的重要性,现在多线程被运用在项目中的次数越来越多,而且面试中多线程也是必问的,所以要引起我们足够的重视将这块的知识学扎实。

1.线程的概念

在说线程之前我们不得不提到进程,从用户角度来说:进程是运行中的程序;操作系统角度来说:进程是操作系统对运行中程序的描述信息–进程描述符–pcb。
线程:在一个程序里的一个执行路线
或者说是:线程是一个进程内部的控制序列
而在Linux中没有为线程设计一个tcb来控制线程运行,而是以进程的pcb来模拟实现线程,也就是说Linux下pcb实际是一个线程,线程是进程pcb的模拟实现,因此Linux的线程也叫做轻量级进程(在Linux系统中,在CPU眼中看到的pcb都要比传统的进程更轻量级),这也就是为什么Linux下多提到的是线程,Linux下进程实际是一个线程组—当中包含一个/多个线程。

因为CPU调度程序运行是调度pcb,因此线程是CPU调度的基本单位。
因为一个程序运行起来就会分配大量的资源给线程组,因此进程是资源分配的基本单位。

同一个进程的线程之间独有的数据:

  1. 栈
  2. 寄存器
  3. errno
  4. 信号频闭字
  5. 线程标识符

同一个进程的线程之间共享的数据:

  1. 数据段,代码段
  2. 文件描述符表
  3. 信号的处理方式
  4. 工作路径
  5. 用户id,组id

2.线程控制

POSIX线程库
想使用以下函数必须引入头文件<pthread.h>
链接这些线程函数库时要使用编译器命令的“-lpthread”选项
1.线程创建
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
thread:用于获取新创建的线程id
attr:线程属性,通常是置NULL
start_routine: 线程的入口函数
arg:传递给线程的参数
返回值:0 失败:!0

2.线程终止
void pthread_exit(void *retval)
retval:用于获取线程退出的返回值

int pthread_cancel(pthread_t thread)
取消一个指定线程,属于被动推出
thread:指定线程的id
主线程退出,进程并不会

3.线程等待
int pthread_join(pthread_ pthread,void **retval);
等待一个线程退出
前提:这个被等待的线程必须是joinable状态的
thread:指定线程id
retval:用于获取线程退出原因
返回值:0 失败:!0

4.线程分离
int pthread_detach(pthread_t thread);
分离一个线程(设置线程的属性从joinable->detach),线程退出后系统将自动回收资源,被分离的线程无法被等待,若是非要用pthread_join则会直接报错返回。
thread:指定分离的线程id
返回值:0 失败:!0
线程默认的属性是joinable

3.线程ID和进程ID对比

进程pid: getpid()
线程tid: pthread_self() //进程内唯一,但是在不同进程则不唯一。
线程pid: syscall(SYS_gettid) //系统内是唯一的(头文件为<sys/syscall.h>)

下面通过一个程序来看三者的区别:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 #include<sys/syscall.h>
  5 
  6 void* pth_start(void* arg)
  7 {
  8     printf("main getpid()=%d,syscall()=%ld,pthread_self()=%ld\n",getpid(),(long int)syscall(SYS_gettid),pthread_self());
  9     while(1){
 10         sleep(2);
 11     }
 12     return NULL;
 13 }
 14 
 15 int main()
 16 {
 17     printf("main getpid()=%d,syscall()=%ld,pthread_self()=%ld\n",getpid(),(long int)syscall(SYS_gettid),pthread_self());
 18     pthread_t tid;
 19     int ret = pthread_create(&tid,NULL,pth_start,NULL);
 20     if(ret!=0){
 21         printf("pthread create error!\n");
 22         return -1;
 23     }
 24     else{
 25         printf("child tid = %ld\n",tid);
 26     }
 27     while(1){
 28         sleep(2);
 29     }
 30     return 0;
 31 }

运行结果如下:
在这里插入图片描述
第一行结果是主线程输出的,后面那行是新线程输出的,可以看到,pid值是一样的,因为同属于一个进程,所以getpid()值是一样的,syscall()的值两个线程是不一样的,而主线程的syscall()和进程的pid值一样,这是因为主线程的pid和线程组的pid值一样,因此也就和进程的pid值一样了,前面的两个pid是在用户态层面来说的,而后面这个pthred_self()是从内核态角度来说的,也是唯一表示线程的id值,pthread_create函数第一个参数指向一个虚拟内存单元,该内存单元的地址即为新创建线程的线程ID,属于 NPTL线程库的范畴。线程库的后续操作,就是根据该线程ID来操作线程的。

为什么syscall()和pthread_self()都求的是线程id为什么会不一样呢?
因为线程库实际由两部分组成:内核的线程支持+用户态的库支持(glibc), Linux早期内核不支持线程的时候glibc就在库中(用户态)以纤程(即用户态线程)的方式支持多线程了,POSIX thread只要求了用户编程的调用接口对内核接口没有要求。
linux上的线程实现就是在内核支持的基础上以POSIX thread的方式对外封装了接口,所以才会有两个ID的问题。

强调一下,线程和进程不一样,进程有父进程的概念,但在线程组里面,所有的线程都是对等关系!

4.线程的优缺点

优点:
1)创建一个新线程的代价要比创建一个新进程小得多
2)与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少的多
3)线程占用的资源要比进程少很多
4)能充分利用多处理器的可并行数量
5)计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
6)I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。
缺点:
性能损失
一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型 线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指
的是增加了额外的 同步和调度开销,而可用的资源不变。

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

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

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

上面多次提到线程导致的安全问题,下节我将会讲解线程安全以及实例!

Linux下多线程交叉打印1~100的奇偶数 Linux下多线程交叉打印1~100的奇偶数 1、要求: 1.有三个线程, 1.1线程1负责把1-99之间的奇数,放入缓冲区 1.2线程2负责把2-100之间的偶数,放入缓冲区 1.3线程3负责把缓冲区的数据读出并打印在终端 2.三个线程之间互斥使用缓冲区 3.线程1和线程2交替放入数据,即按照1,、2、3……的顺序放入 4.线程3按照1,、2、3……的顺序取出数据打印 5.只有当数据被线程3取走以后,线程1和线程2才能往缓冲区放数据 6.只有当线程1或线程2往缓冲区放入数据后,线程3才能取走数据 阅读详情

相关推荐

从零开始:TexLive(Latex)安装与配置全指南

本文提供了一份详尽的TexLive(Latex)安装与配置全指南,旨在帮助用户从零开始快速搭建LaTeX工作环境。内容涵盖从镜像下载、安装步骤详解、环境验证到高效编辑器(如VS Code)配置,并特别强调了中文排版支持与宏包管理,确保用户能顺利处理学术论文等专业文档的排版需求。

weixin_29284885的博客 903

【Linux C | 多线程编程】线程的创建、线程ID、线程属性

本文介绍了线程创建相关的内容,包括pthread_create函数的详细介绍和使用例子,然后依次介绍该函数第一个参数相关的线程ID知识以及第二个参数相关的线程属性知识。读完完整地了解线程的创建。

wkd_007的博客 3966

保姆级教程:在Win10/Win11上搞定AppScan 10.0.0安装与许可证激活(含常见报错解决)

本文提供AppScan 10.0.0在Win10/Win11上的详细安装与许可证激活指南,涵盖环境准备、分步安装、文件替换技巧及常见报错解决方案。通过专业的安全测试工具部署实践,帮助用户高效完成安装并避免常见陷阱,提升Web应用安全扫描效率。

weixin_30800987的博客 425

linux操作系统——线程控制+线程封装

我们前面谈到了由于用户只认线程,而linux操作系统是通过用轻量级进程模拟线程,并不是真正的线程,所以linux的解决方案是中间添加一层软件层,向上提供用户所认为的线程接口,向下则调用对应的Linux提供的轻量级进程的接口与用户调用的线程接口与之对应,所以当我们有五个线程时我们都可以看到有5个不同的LWP。Linux天然的就知道进程管理的那一套方法,知道怎么创建,如何被调度,进程状态是运行还是等待,知道怎么回收,怎么终止等等这一系列对进程的管理。那么它又是怎么知道创建了几个,而是什么呢?

希望自己从编程小白变成大佬 840

激光三角测量法:斜射与直射式技术的原理与应用解析

本文深入解析激光三角测量法中斜射式与直射式技术的原理、应用及对比。斜射式适用于高精度小范围测量,尤其擅长处理反光表面;直射式则适合大范围位移检测,结构更简单。文章详细介绍了两种技术的光路分析、数学建模、应用场景及选型建议,并探讨了系统校准与误差分析方法,为工业检测领域提供实用参考。

weixin_29280219的博客 414

实战指南:基于Windows Server构建企业级AAA认证体系

本文详细介绍了如何在Windows Server环境下构建企业级AAA认证体系,涵盖AD域服务部署、NPS服务器配置及华为设备对接实战。通过整合Radius协议与AD域账号管理,实现网络设备的统一认证与权限控制,提升企业IT安全管理效率。特别适用于需要零成本实现AAA认证的中大型企业。

weixin_28304023的博客 422

Linux下创建所线程

一. 线程 线程是轻量级的进程(LWP:light weight process),在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。操作系统会以进程为单位,分配系统资源,可以这样理解,进程是资源分配的最小单位,线程是操作系统调度执行的最小单位。 1.进程有自己独立的地址空间,多个线程共用同一个地址空间 线程更加节省系统资源,效率不仅可以保持的,而且能够更高 在一个地址空间中多个线程独享:每个线程都有属于自己的栈区,寄存器 (内核中

weixin_52694360的博客 1512

【机器人】线性方程最小二乘解法对机械臂DH参数进行标定

1.前言 看了一篇文章,觉得里面的DH参数标定法讲的很清晰,便使用Matlab复现了一下,效果还可以,特写此文记录。 2.原理 2.1.误差最佳值的最小二乘计算 有研究结果表明:几乎95%的机器人位置误差都是由机器人内部运动学的不准确描述引起的,所以对DH模型参数进行标定是很有必要的。 DH参数物理含义:选自《机器人学、机器视觉与控制-Matlab基础》 当DH参数确定后,我们...

要恰饭得嘛 1万+

系统调用SystemCalls-3-linux进程线程创建

Linux进程、线程创建所使用的系统调用是统一的,都通过sys_fork/sys_clone/sys_vfork系统调用来实现,内部调用的do_fork内核调用。

春夜喜雨的专栏 567

【深度学习新浪潮】ISP芯片算法技术简介及关键技术分析

ISP(Image Signal Processor)芯片作为现代影像系统的核心组件,负责对图像传感器输出的原始信号进行后期处理。ISP的主要功能包括线性纠正、噪声去除、坏点修复、色彩校正以及白平衡调整等,这些处理步骤对于提高图像质量和视觉效果至关重要。随着科技的进步,ISP芯片不仅提升了图像的清晰度和色彩准确性,还通过高效的算法增强了拍摄体验,尤其是在低光环境下的表现。

专注:太空算力、AI infra、异构调度、大模型成本工程 1223

RT-DETR训练自己的数据集(从代码下载到实例测试)

在Windows10上配置CUDA环境教程是百度提出的一种实时目标检测模型。RT-DETR采用了与DETR相同的编码器和解码器结构,但对其进行了大量的优化,在保持较高检测精度的同时,实现了实时目标检测,为目标检测领域提供了一种新的有效解决方案,具有广泛的应用前景,如自动驾驶、智能监控、机器人等领域。以上是RT-DETR官方的论文和代码,详细介绍了RT-DETR的构成和实现。在YOLOv10中也实现了RT-DETR的代码,所以本文使用YOLOv10的项目文件进行RT-DETR的训练和测试。YOLOv10。

Limiiiing的博客 4万+

Linux下获得线程ID syscall(224)

From: http://blog.163.com/onx0320@126/blog/static/164736436201252574720314/ 对于Linux线程,也许大家并不陌生,而我们通常所说的线程是指基于POSIX标准的线程,而Linux下除了兼容POSIX标准,而且提供线程在内核级的支持。     早在Linux kernel2.4之前,Linux的线程(LinuxTh

JoeBlackZQQ的专栏 3170

手把手教你学Simulink——基于Simulink的无感FOC(滑模观测器+PLL)实战

本文详细介绍了基于Simulink的无感FOC(滑模观测器+PLL)实现方法。主要内容包括:1)SMO+PLL原理精讲,阐述滑模观测器核心思想和PLL的作用;2)系统架构全景图展示;3)Simulink建模全流程,从基础FOC框架到SMO和PLL模块的实现;4)关键参数整定指南和工程实践要点;5)仿真结果分析及常见问题解决方案。该方法可有效替代机械传感器,降低成本并提高可靠性,适用于空调压缩机、电动汽车水泵等工业场景。文章还提供了详细的调试建议和动手实践指导。

MHD0815的博客 83

Linux线程1

Linux线程1

CL2426的博客 385

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Linux-线程1

0、章节引用 优快云的lc_29503203用户的《浅析Linux下的task_struct结构体》 优快云的CallMeRiaan用户的《Linux内存之Cache》 优快云的misiter用户的《lwp和线程区别》 1、课程目标 线程概念(了解) 线程特点(了解) 线程创建(熟练) 小结 2、进程 进程是为了执行程序分配的总称,进程创建会分配一下资源(内存资源,CPU资源等)。 每一个进程有自己独立的地址空间,代码、数据,互不影响。 Linux为每一个进程创建task_struct(任务

weixin_41332204的博客 139

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

linux两个线程交替执行,如何用C语言实现两个线程在Linux环境下打印1~100

怎么用C语言实现两个线程在Linux环境下打印1~100#include#include#include#includeintn=1;intN=100;pthread_mutex_tmutex;pthread_mutex_init(&mutex);void*func1(){while(n{pthread_mutex_lock(&mutex);printf(...

weixin_28755331的博客 1547

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【Linux】Linux之多线程1

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

m0_73839343的博客 933

【Linux】多线程1——线程概念与线程控制

初步认识线程的概念,并熟悉线程控制接口

Pursue quality, not quantity. 1613

Linux——线程1

若我们已经创建好一个进程,此时再创建进程,此时就会有俩套task_struct,mm_struct,页表我们想在一个进程的基础上,在创建一个进程,而且这个新的进程只创建PCB(task_struct),这个PCB指向父进程对应的地址空间。我们想以上面这种方式创建多个进程,而且通过一定的技术手段,将当前进程的“资源”,以一定的方式划分给不同的task_struct(如多个进程执行不同的代码)。而且对于CPU来说,这么多PCB不会影响到CPU。

weixin_49449676的博客 291

【Linux】多线程1——线程

自己独立的进程地址空间和独立的页表本身就具有独立性。只创建task_struct,那么创建的结果就是下面这样的:“线程是进程内部的一个执行分支”。也就是说曾经这个进程申请的所有资源,几乎都是被所有线程共享的。注意: 单纯从技术角度,这个是一定能实现的,因为它比创建一个原始进程所做的工作更轻量化了。下面用蓝色方框框起来的内容,我们将这个整体叫做进程。换言之,当我们创建进程时是。

2301_80224556的博客 957

linux 线程 1.1 — 线程开发 API

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

qq_45831156的博客 427

Linux线程(1): 线程的创建

1. 概念:    线程与进程是不同的, 准确地说, 进程可以由多个线程组成, 线程是进程的组成元素. 默认情况下, 一个进程只是由一个线程构成, 它串行执行该进程要执行的任务. 多线程情况下, 每个线程执行各自的任务, 它们之间更多是并行的. 线程的作用具体有: 在单进程环境中执行多个任务. 共享该进程的组成部件, 如文件描述符和内存, 但需要较为复杂的机制.

代威涛的主页 1902

Linux——多线程1

线程是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 。

qq_63943454的博客 781

Linux 线程(1)线程创建

1. 线程 2.

矩阵实验室 1405

linux多线程编程基础1

《linux多线程编程基础1》,作者:GOD_YCA,原文链接:http://www.cnblogs.com/GODYCA/archive/2013/01/23/2873625.html 分享自:博客园Android客户端(http://android.walkingp.com/cnblogs/)...

weixin_34253126的博客 135
上一篇: git的安装及linux下git的使用
下一篇: 结构体内存对齐详解(同比C++类的大小计算)
Python_programer
博客等级 码龄9年 25粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值