首页 > 系统相关 >理解进程,线程,协程

理解进程,线程,协程

时间:2024-07-19 22:40:01浏览次数:13  
标签:协程 操作系统 用户 线程 内核 进程

为什么需要进程,线程,协程?

举个例子,比如:我们 go run main.go,启动一个 go 程序,从磁盘读取可执行文件,将 CPU 要执行的命令加载到内存中,然后 CPU 就一直:1. 读取内存指令,2. 执行指令,循环往复。那我们从磁盘读取的可执行文件,读到内存,他放在什么地方呢?

我们需要找一个结构体来记录这些东西,比如加载一个程序,第一条命令执行什么?所以我们发明了一个结构体,也就是我们的进程,操作系统分配资源的基本单位。

在多核 CPU 时代,如果我们想要充分利用核心,可以选择让不同进程跑到不同 CPU 上,但这又存在其他的问题,进程之间会带来额外的开销,比如:进程间通信。增大了编程难度的同时,也增加了系统开销。

一个进程最开始都是 main 函数开始的,可以把执行 main 函数的过程看作是一个执行流,一个进程下面有多个小任务同时执行,可以看作有多条执行流,给这个执行流起个名字,那就是线程,让这些线程去执行不同的函数(不同的任务)就好了。线程的内存地址是直接从进程里面划分出来的,这也是线程比进程创建快的一个原因,线程直接划分进程内存,而进程还需要操作系统进行分配。

对于进程和线程,他们的本质就是状态机(状态机其实就是对某种事物状态变化的一个抽象,这种抽象可以帮助我们更容易理清思路,能够明确知道,某种事物在某个时间点会有某种状态,或者经历某种操作,就切换到某种状态),而操作系统同样是一个状态机,不过他是来调度线程/进程的,可以叫做调度状态机的状态机。

Linux 的 二把手 alan cox 说过一句话:计算机就是状态机,线程是为不懂状态机的程序员准备的

其实线程和进程都是对底层的一种高度抽象,线程同样,线程这个概念甚至在 Linux 里面他都不算存在。进程在 Linux 里面是一个 task_struct,线程同样是,只不过线程是共享了进程的空间,可以看作创建了一个线程,其实就是创建了一个新进程,一个可以共享原来进程内存空间的的进程,我们把它抽象的叫做线程。

线程有两种组织形式,简单来说:

1)用户级线程

我们将操作系统分为两态,用户态和内核态,用户态就是用户可以看到的空间,而用户级线程就是从用户视角可以看到的线程,而用户级的线程在切换的时候在用户空间就能完成,不需要切换到核心态,线程切换的开销比较小,效率高。

2)内核级线程

线程调度、切换等工作都由操作系统内核负责。

在支持内核级线程的系统中,根据用户级线程和内核级线程的映射关系,可以划分为几种多线程模型:

一对一:一个内核级线程对一个用户级线程

一对多:一个内核级线程对多个用户级线程

多对多:多个内核级线程对多个用户级线程

各有优缺点,具体是什么策略主要看使用的系统调用,这里我就不详细展开了,可以看看这个一对多模式的图:

在用户程序中,比如线程库,组织实现的一个执行流,他也起个别名叫做线程,因为内存在用户空间,所以叫用户线程合适一些,可以看作是一个 C语言程序自己实现了一套线程组织方式,但实际上,最终调度还是要通过内核线程,举个例子:像 pthread 这样的线程库,他可以创建n个用户级线程,但其实底层就是一个线程负责

用户级线程也是一个抽象的状态机,只不过是在用户空间抽象的,而不是内核空间,那为什么要抽象一个用户级线程呢?因为:如果都用内核级线程的话,线程切换每次都要在用户态和内核态之间来回走,系统开销大

用户级线程优点是:

1.管理开销小:创建、销毁不需要系统调用,也不占用内核内存

2.切换成本低:用户空间程序可以自己维护,不需要通过操作系统调度

但他也有缺点:

1.用户程序在管理,当它进行 I/O 的时候,无法利用到内核的优势,需要频繁进行用户态到内核态的切换

2.无法利用多核优势:比如操作系统调度的仍然是这个线程所属的进程,所以无论每次一个进程有多少用户态的线程,都只能并发执行一个线程,无法实现并行,因此无法利用多核 CPU 的优势

3操作系统无法优化用户线程的调度,因为对于操作系统,用户线程是完全透明的(感知不到),如果用户线程阻塞了,操作系统也无法快速切换阻塞的用户线程

但 There is no silver bullet!没有最好的解法,只有最适合的业务场景。

那为什么需要协程呢?

我们都知道,操作系统基本的都是分时系统,也就是给每一个进程/线程都分配时间片,时间片用完了,就打断该线程的执行,让其他线程享受 CPU,这会带来并发安全的问题(我们可以通过加锁解决),但有些线程其实是可以相互配合的,如果在一个线程还没有执行完就抢占式的把 CPU 资源分配给其他线程,很可能导致意想不到的执行紊乱情况

操作系统的分时机制的好处是让每个线程都能享受到 CPU 资源,但有些场景也是坏处,比如我同一个进程下的多个线程,其实我可以让他们相互配合,协作的,但由于操作系统的分时抢占式,就容易打破协作的平衡

“非抢占式多任务”,当出现一个线程事情没做完,但还差一点点的时候,其他线程就先等一会儿,等做完了就自动交出 CPU 控制权,这里体现出的协作,我们给这种形式的执行流起一个名字,那就是所谓的协程,每次执行中,协程之间的具体执行顺序可能千变万化,但协程执行权切换却只会发生在用户明确放弃执行权之后:比如你明确执行了 yield 语句时(让出 CPU 的语句)

但是,一般很难开发出一套好用的协程库,所以现在用的最多的还是线程。

进程,线程,协程有什么不同?

进程与线程有什么不同?

1)从定义上说,进程是操作系统进行资源分配和调度的基本单位,而线程是进程的执行单元,共享进程的资源

2)具体来说,进程就是运行起来的可执行程序,当我们运行一个可执行程序的时候,就会创建一个或多个进程,创建进程的时候需要分配空间,比如:栈区、文件映射区、堆区、静态区、常量区、代码段,这就是为什么进程也被称为是资源分配的基本单位;每个进程中都有唯一的主线程,有且只有一个,主线程和进程是相互依存的关系,主线程结束进程也会结束

3)每个进程有自己的独立地址空间,不与其他进程分享;一个进程里可以有多个线程,彼此共享同一个地址空间。堆内存、文件、套接字等资源都归进程管理,同一个进程里的多个线程可以共享使用。每个进程占用的内存和其他资源,会在进程退出或被杀死时返回给操作系统

4)并发应用开发可以用多进程或多线程的方式,多线程由于可以共享资源,效率较高;反之,多进程默认是不共享地址空间与资源,开发较为麻烦,共享数据时效率较低。但多进程安全性较好,在某一个进程出问题时,其他进程一般不受影响,而在多线程的情况下,一个线程执行了非法操作会可能导致整个进程退出

协程和线程有什么区别?

1)协程的开销比线程更小

2)协程可以很好的应对非抢占式多任务场景,大家一起办好一件事;而协程在操作系统的分时机制下,容易出现导致意想不到的执行紊乱情况

3)线程可以实现并行,但协程不行,他与用户级线程有些类似,所以他也拥有用户级线程的优点:创建、销毁不需要系统调用,也不占用内核内存,开销小;在用户空间程序可以自己维护协程,不需要通过操作系统调度

这里要注意的是,go 的协程 goroutine 其实不算操作系统的协程,他是 go 自己实现的便于并发编程的东西,这个的东西又有很多可以说道的地方,不过这里就不展开了

标签:协程,操作系统,用户,线程,内核,进程
From: https://www.cnblogs.com/qimoxuan/p/18312504

相关文章

  • 线程池(C++11)
    已经有现成的实现,本博客摘抄讲解附源码链接。参考的博客质量已经非常高,避免找来找去。1、避免频繁创建、销毁线程,实现复用。思路如下:2、线程函数多种多样,如何封装成统一的函数类型void()第一次封装我们使用bind()函数将多个参数的函数封装为没有形参的package_task对象,因为p......
  • Linux中进程间通信--匿名管道和命名管道
        本篇将会进入Linux进程中进程间通信,本篇简要的介绍了Linux中进程为什么需要通信,进程间通信的常用方式。然后详细的介绍了Linux进程间的管道通信方式,管道通信分为匿名管道和命名管道,本篇分别介绍了其实现的原理,以及使用Linux中的系统调用,用代码实现了这两......
  • 【Linux】Linux进程揭秘:从理论到实践的深度探索之旅
    目录前言:操作系统简介概念设计目的理解进程:程序的执行之魂进程和程序的联系与区别 描述进程-PCB进程的标识符 进程状态 状态转换僵尸进程孤儿进程前言:操作系统简介概念操作系统(英语:OperatingSystem,缩写:OS)是一组主管并控制计算机操作、运用和运行硬件、软......
  • Java中的线程池管理与并发性能优化
    Java中的线程池管理与并发性能优化大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何在Java中有效管理线程池,以及如何通过优化并发性能提升应用的效率。线程池是管理线程的一个重要工具,能够提高系统的并发处理能力,并减少线程创建和销毁的......
  • C++多线程
    多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。基于进程的多任务处理是程序的并发执行。基于线程的多任务处理是同一程序的片段的并发执行。多线程程序包含可以同时运行的两个或多个......
  • Java中的多线程编程与锁机制解析
    Java中的多线程编程与锁机制解析大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天,我们将深入探讨Java中的多线程编程与锁机制。多线程编程在现代应用开发中至关重要,它允许程序同时执行多个任务,从而提高程序的响应性和性能。我们将通过代码示例来解析Jav......
  • 分享php两个实用类:单线程调用和集合类
    单线程类<?php/***单线程执行方法*/namespacebackend\components;classSingleThread{/***单线程执行方法*@param$methodstring'\backend\components\Tool::test'*@param$paramarray方法$method的参数*@returnvoid*/......
  • 查看电脑内核及线程数量
    1.第一种方法:进入电脑:win+r进入命令提示符号界面输入:wmic进入命令行界面1.1cpugetNumberOfCores内核数量1.2cpugetnumberoflogicalProcessors线程数量1.3查看电脑处理器发现是20核,比14核多了6核心,是因为超线程技术的原因;超线程技术把多线程处理器内部的两......
  • 从慢到快:如何用JDK 21虚拟线程重塑性能极限
    JDK21引入了虚拟线程(VirtualThreads),这是Java语言和虚拟机中的一个重要新特性。虚拟线程的目的是简化并发编程,使得处理大量并发任务变得更加高效和易于管理。以下是虚拟线程的概念、优势和劣势,以及相关的示例说明。虚拟线程概念虚拟线程是一种轻量级的线程,设计用来简......
  • 组件服务:8000401a 因为配置标识不正确,系统无法开始服务器进程。请检查用户名和密码
     报错日志:StartCADException:RetrievingtheCOMclassfactoryforcomponentwithCLSID{DED89DB0-45B6-11CE-B307-0800363A1E02}failedduetothefollowingerror:8000401a因为配置标识不正确,系统无法开始服务器进程。请检查用户名和密码。(0x8000401A).【记录时间......