[转帖]进程 线程和 协程

进程,线程 · 浏览次数 : 0

小编点评

**内核态线程** * 概念清晰,容易开发 * 线程切换的时机由操作系统决定,抢占式 * 线程上下文保存/载入成本高 * 效率低,线程数量多时,线程切换开销甚至能超过业务代码 **用户态线程** * 线程切换的时机由用户代码完全控制 * 线程上下文保存/载入成本低 * 效率高,线程数量多时,用户态线程可以并行运行 * 每个用户态线程都是一个独立的单线程进程

正文

作者:ScratchLab
链接:https://www.zhihu.com/question/308641794/answer/2867920715
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

线程有两种实现方式:内核态线程和用户态线程。早期,内核态线程由于概念清晰,对开发者友好,在与用户态线程的竞争中胜出。但随着互联网的发展,用户态线程凭借其线程切换成本低、竞态少等特点重新回归开发者视野,并逐步发展成最新的并发模型--协程。下面我们从线程切换和竞态两个方面介绍一下内核态线程和用户态线程。从线程切换的角度来讲,进程与线程基本原理是一样的。下图展示了内核态线程切换的一个大概的过程:<img src="https://pic1.zhimg.com/50/v2-170cedfa1203204c13fafc91283bd031_720w.jpg?source=1940ef5c" data-caption="" data-size="normal" data-rawwidth="467" data-rawheight="501" class="origin_image zh-lightbox-thumb" width="467" data-original="https://pic1.zhimg.com/v2-170cedfa1203204c13fafc91283bd031_r.jpg?source=1940ef5c"/>当前时刻,线程A正在运行。此时,来了一个时钟中断,系统由ring3的线程A跳转到ring0的时钟中断handler中。当handler认为需要切换线程时,会将线程A的上下文保存到线程A的控制块中。然后,handler根据调度算法从就绪线程中选择一个来运行,假设handler选择了线程F来运行。handler会将线程F的上下文从其控制块中载入到当前线程。完成上下文保存/载入工作后,handler退出,并跳转到ring3。此时,ring3中运行的就是线程F了。从上述流程我们可以发现,内核态线程有以下特点:线程切换的时机由操作系统决定(抢占式),线程无法对切换时机做任何假设。因此,多线程程序开发时必须考虑竞态线程切换时涉及到特权级的跳转和线程上下文的保存/载入这就造成了内核态线程切换时的成本非常高,线程数量多时,线程切换的开销甚至能超过业务代码。下面,我们看一下用户态线程的切换过程。下图展示了用户态线程切换的一个大致过程:<img src="https://picx.zhimg.com/50/v2-1fe9d8624b94078935205e93d828dca6_720w.jpg?source=1940ef5c" data-caption="" data-size="normal" data-rawwidth="456" data-rawheight="368" class="origin_image zh-lightbox-thumb" width="456" data-original="https://picx.zhimg.com/v2-1fe9d8624b94078935205e93d828dca6_r.jpg?source=1940ef5c"/>当前时刻,线程A正在运行。线程A运行一段时间后主动退出,将其上下文保存到线程A的控制块中。然后,线程A根据用户代码从其他线程中选择一个来运行。假设用户代码要求线程A退出后线程F继续运行。线程A会将的线程F的上下文载入到当前线程中,并跳转到线程F的代码中运行。各用户态线程不断的运行、退出,形成这样一个序列:A线程运行A线程退出,选择F来运行F线程运行F线程退出,选择D来运行D线程运行D线程退出,选择E来运行...A线程运行A线程退出,选择B来运行从以上介绍中我们可以看到,没有了时钟中断,某个线程运行时无法被强制退出,只有主动退出,其他线程才有运行机会。用户态线程的调度就依靠各线程在合适的时机主动退出,让其他线程获得运行机会来进行。各用户态线程彼此协作,推动程序的运行,因此,用户态线程又称作协程。从上述流程我们可以看出,用户态线程有以下特点:各用户态线程本质上是在一个单线程进程上执行的,线程调度的时机由用户代码完全控制,因此不用考虑竞态线程切换过程不涉及特权级的跳转线程切换时也涉及到上下文的保存/载入,但是各用户态线程是在一个单线程进程上运行的,可以共享许多数据,因此用户态线程上下文的数据量远远小于内核态线程上下文从以上特点我们可以看到,用户态线程切换的开销非常低,且系统不会限制用户态线程的数量,非常适合高并发。

与[转帖]进程 线程和 协程相似的内容:

[转帖]进程 线程和 协程

作者:ScratchLab链接:https://www.zhihu.com/question/308641794/answer/2867920715来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 线程有两种实现方式:内核态线程和用户态线程。早期,内核态线程由于概念清晰

[转帖]协程切换和线程切换

先说结论:协程切换比线程切换快主要有两点: (1)协程切换完全在用户空间进行,线程切换涉及特权模式切换,需要在内核空间完成;(2)协程切换相比线程切换做的事情更少。 协程切换只涉及基本的CPU上下文切换,所谓的 CPU 上下文,就是一堆寄存器,里面保存了 CPU运行任务所需要的信息:从哪里开始运行(

[转帖]总结:协程与线程

一、介绍 本文主要梳理下进程,线程,协程的概念、区别以及使用场景的选择。 二、进程 我们知道,一切的软件都是跑在操作系统上,真正用来干活 (计算) 的是 CPU。早期的操作系统每个程序就是一个进程,知道一个程序运行完,才能进行下一个进程,就是 “单进程时代”。一切的程序只能串行发生。 早期的单进程操

[转帖]Redis如何绑定CPU

文章系转载,便于分类和归纳,源文地址:https://www.yisu.com/zixun/672271.html 绑定 CPU Redis 6.0 开始支持绑定 CPU,可以有效减少线程上下文切换。 CPU 亲和性(CPU Affinity)是一种调度属性,它将一个进程或线程,「绑定」到一个或一组

[转帖]Redis如何绑定CPU

文章系转载,便于分类和归纳,源文地址:https://www.yisu.com/zixun/672271.html 绑定 CPU Redis 6.0 开始支持绑定 CPU,可以有效减少线程上下文切换。 CPU 亲和性(CPU Affinity)是一种调度属性,它将一个进程或线程,「绑定」到一个或一组

[转帖]《Linux性能优化实战》笔记(24)—— 动态追踪 DTrace

使用 perf 对系统内核线程进行分析时,内核线程依然还在正常运行中,所以这种方法也被称为动态追踪技术。动态追踪技术通过探针机制来采集内核或者应用程序的运行信息,从而可以不用修改内核和应用程序的代码就获得丰富的信息,帮你分析、定位想要排查的问题。 以往,在排查和调试性能问题时,我们往往需要先为应用程

[转帖]Oracle 通过 Exadata 云基础设施 X9M 提供卓越的数据库性能和规模

https://www.modb.pro/db/397202 32个节点的RAC 服务器 每个服务器 两个 64核心的AMD CPU 四个线程干管理 252个线程进行数据库处理 252*32=8064 Exadata Cloud Infrastructure X9M 以相同的价格比上一代产品多 2.

[转帖]一个轻量的Linux运维监控脚本

https://zhuanlan.zhihu.com/p/472040635 写在前面 我的需求 嗯,有几台很老的机器,上面部署的几个很老的应用 我需要每周对机器上的一些内存,磁盘,线程,应用和数据库进行巡查监控,输出运维报告 因为是很老的东西,所以不敢随便乱动,怕掉坑里. 每次巡查都是通过通过命令

[转帖]Jmeter脚本录制:Jmeter5.0脚本录制

第一部分进行jmeter设置 第一步:在JMeter中添加线程组 第二步:在线程组下添加HTTP请求默认值 添加->配置元件->HTTP请求默认值,设置服务器IP和端口号 第三步:在线程组下添加HTTPcookie管理器 第四步:添加HTTP代理服务器 在测试计划上,右击添加“非测试原件”->“HT

[转帖]关于iostat的问题,svctm数据不可信

使用FIO对磁盘进行压力测试,使用1个线程对磁盘进行随机读,设置单次read的数据块分别为128KB和1M,数据如下: (1)单次IO数据块为128KB (2)单次IO数据块为1M 从上面的数据可以看出,当单次IO的数据块变大,服务时间svctm反而变短,这明显不符合常规认知。 查阅到fio的相关资