Linux之多线程第一部分:多线程的概念

什么是线程

在linux当中线程可以认为是进程的一部分,他与进程共享一份地址空间,而不是新建一个线程就新建一份地址空间(windos操作系统是这样的)。然而,本质上linux是没有线程的概念的,因为CPU在对每个线程处理时,都会把它当作进程来处理,只不过线程在CPU眼里是更轻量级的进程,所以线程只是我们用户理解,在操作系统中他都认为这些是进程,只不过线程可以看作为比进程小一点的进程,下面将画图说明线程在linux中与进程的关系:
在这里插入图片描述

上图说明了在Linux系统中线程与进程的关系:
1.线程与进程共用一份地址空间,只不过线程要访问的数据比进程要少,因此他在CPU眼里是属于轻量级的进程。
2.一个PCB就是要被调度的执行流
3.Linux中没有专门为线程设计TCB,而是用进程的PCB来模拟线程
根据进程与线程的关系我们来总结下进程的概念:
进程内部是有多个执行流
创建进程的成本是很高的:时间+空间
创建进程使用的资源很多(0>>>>>1)
以内核视角来看:
进程是承担系统分配资源的基本实体
线程是CPU调度的基本单位,承担进程一部分资源的实体(进程划分资源给线程)

总结一句话就是:进程向系统要资源,而线程是向进程要资源

线程与接口关系的认识

因为Linux是用进程来模拟线程的,因此Linux本身不会提供线程的操作接口,而是给我们提供在同一个地址空间创建PCB的方法,分配资源给指定的PCB的接口。
这样对用户很不友好,因为如果要使用的话用户还要自己创建线程,释放线程,等待线程等,太麻烦。
因此,大佬们为我们在用户层对Linux轻量级进程(线程)接口进行封装,给我们打包成库,让用户直接使用库,原生线程库(用户层)

线程与进程的共享与私有

所有的轻量级进程(可能是"线程")都在进程内部(同一个地址空间:标识进程能看到大部分资源)运行
进程:具有独立性,可以有部分共享资源(管道,ipc资源)
线程:大部分资源是共享的,有部分是私有的(PCB,栈, 寄存器中存储的当前线程的上下文)
线程共享的环境包括:(6个)
(1)进程代码段、(2)进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、(3)进程打开的文件描述符、(4)信号的处理器、(5)进程的当前目录(6)进程用户ID与进程组ID。

总结:只要记住线程的栈和上下文是私有的其余大部分都是共享的

接下来我们证明下Linux线程是用进程模拟的
首先介绍先创建线程的函数:
在这里插入图片描述

在这里插入图片描述
注意上面说过使用线程要用到第三方库,因此我们编译时要加上pthread库
在这里插入图片描述
在这里插入图片描述
运行发现主进程和线程的pid都是25584证明此时只有一个进程,但是有两个执行流!!
kill -9 杀掉该进程两个线程都终止了,再次证明两个执行流是同一个进程的。
在这里插入图片描述
下图两个线程的PID是一样的, LWP的意思是轻量级线程,OS内核处理线程时候不看PID,看的是LWP,说明:Linux OS调度的时候看的是LWP,只不过这两个线程在自己的PCB中保存的PID是一样的,证明这两个线程属于同一个进程的,LWP证明了我们两个是不同的执行流!
在只有一个执行流的时候,即只有一个进程,PID == LWP
在这里插入图片描述

线程的优点

1.创建一个新线程的代价要比创建一个新进程小得多
2.与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
3.线程占用的资源要比进程少很多
4.能充分利用多处理器的可并行数量
5.在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
6.计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
计算密集型大多数指的是:加密、大数据运算等。主要使用的是CPU资源。但这并不意味这我线程越多,我能同时计算的数据就越多,效率就提升了。
一般使用CPU资源的工作创建多少个线程是要跟自己的CPU核数有关的:CPU核数即一个CPU由多少个核心组成,核心数越多,代表这个CPU的运转速度越快,性能越好。对于同一个数据处理,一核CPU相当于1个人处理数据,双核CPU相当于2个人处理同一个数据,4核CPU相当于4个人去处理同一个数据,因此处理核心数越多,CPU的工作效率也就越高。
如果你是单核的CPU,说明你同时只能处理一个线程,那你最高的效率就是创建一个线程,多了反而会导致线程间被过度切换。
7.I/O密集型应用,为了提高性能,将I/O等待的时间重叠。线程可以同时等待不同的I/O操作。
I/O密集型大多数指的是:网络下载、云盘、在线直播、看电影等。主要用内存外设的IO资源。
IO密集型会允许我们多一些线程,但并不是无脑多,因为进行IO操作,比如我们下载,看电影,大部分时间都在等待IO就绪。比如我们用微信发消息,线程大部分时间都用在等待我们发消息,因此多一些线程,会让我们IO等待的时间重叠,提高效率。

我们大部分的应用都是 计算密集型+I/O密集型这样的应用,最典型的例子:打游戏!!!线程一边要同步大量的数据(I/O),一边还要计算(CPU)!!

线程的缺点

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

2.健壮性降低
编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
一般,你当前进程里有多个线程(执行流),当其中一个线程崩溃了,操作系统会向总进程发信号,而不是出问题的那个线程,导致整个进程都被杀掉了。

3.缺乏访问控制
进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
因为线程之间的资源大部分是共享的,所以很容易一个线程误操作了其他线程在处理的工作,调试找问题困难。

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

进程和线程的关系如下图:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针对你的第一个问题,我理解你想了解Linux多线程通信的流程,下面是一个简单的C/S模型的多线程通信流程图: ``` Server Client -------- -------- | main | | main | -------- -------- | | | | -------- -------- | t1 | | t1 | -------- -------- | | -------- -------- | t2 | | t2 | -------- -------- | | -------- -------- | t3 | | t3 | -------- -------- | | | | | | -------- -------- | t4 | | t4 | -------- -------- | | | | | | -------- -------- | t5 | | t5 | -------- -------- | | | | | | -------- -------- | t6 | | t6 | -------- -------- | | | | | | -------- -------- | t7 | | t7 | -------- -------- | | | | | | -------- -------- | t8 | | t8 | -------- -------- | | | | | | V V -------- -------- | IO | | IO | -------- -------- ``` 具体说明如下: 1. Server和Client进程都有一个main线程,用于启动其他线程,执行初始化等操作。 2. Server和Client进程都有多个工作线程t1-t8,用于执行具体的任务。 3. 在Server进程中,工作线程t1-t8之间可以通过共享内存、socket等方式进行通信,从而完成数据的交换。 4. 在Client进程中,工作线程t1-t8同样可以通过共享内存、socket等方式进行通信,从而完成数据的交换。 5. 在Server和Client进程中,工作线程t1-t8均可以执行IO操作,例如读写文件、发送接收网络数据等。 针对你的第二个问题,关于Linux C多线程的入门,这里给出一些简单的导: 1. C语言中支持多线程编程的库主要包括POSIX线程库(pthread)、OpenMP、TBB等。 2. 在Linux环境下,使用pthread库进行多线程编程是比较常见的方式。该库提供了创建线程、线程同步、线程通信等功能,可以方便地实现多线程编程。 3. pthread库中常用的函数包括pthread_create、pthread_join、pthread_mutex_init、pthread_mutex_lock、pthread_cond_init等,这些函数分别用于创建线程、等待线程结束、初始化线程锁、加锁、初始化条件变量等操作。 4. 多线程编程需要注意线程安全性,避免出现竞争条件、死锁等问题。在编写多线程程序时,需要仔细考虑线程之间的数据共享和通信,以保证程序的正确性和性能。 希望以上内容对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值