一个故事讲完进程、线程和协程(操作系统基础知识)

原文链接:https://mp.weixin.qq.com/s/zuWRx1FGuBC-_HwuA7jK3w

转自:码农翻身(微信号:coderising)

很久以前,有两个程序,暂且称他们旺财和小强吧。

旺财和小强这两个程序都很长,每个都有十几万行。 他们两个的人生价值就是到CPU上去运行,把运行结果告诉人类。

CPU是稀缺资源,只有一个,他们俩必须排着队,轮流使用。

旺财从头到尾执行完了,让出CPU, 让小强从头儿去执行。

人类把这种处理方式叫做批处理

进程

长久以来,两人相安无事。 后来CPU的速度越来越快, 远远超过了内存,硬盘的速度。

人类想到,这批处理系统的效率有点低啊,你看当小强需要从硬盘上读取数据的时候,CPU也一直在等待,这是多大的浪费啊!这时候完全可以让旺财来运行一下嘛!

当然得保存好小强的执行现场:具体执行到那一行程序指令了, 函数调用到什么层次了,每个函数调用都有什么样的参数,CPU寄存器中的值… 等等一系列东西。

如果不把小强的执行现场给保存下来,等到小强的数据从银盘读完了,就没法回到中断处来继续执行了。

这个执行现场,再加上小强的代码,就是一个执行中的程序,被称为进程

旺财和小强在运行的时候,也被改造成了进程。

人类还规定:进程不能长时间占据CPU, 只能在CPU上执行一小会儿,然后马上切换到别的进程去执行。

旺财和小强不以为意:不就是执行一会儿,歇一会儿,然后继续执行嘛!

但是他们不知道的是,由于CPU运行速度超快,旺财和小强虽然在不断地切换运行,在人类那缓慢的世界里看来,旺财和小强好像是同时在执行一样。 这就是并发

(在人类看来,小强和旺财似乎是在同时执行)

多年以后,他们俩才真正地实现了并行: 在一个豪华电脑中,每人都被分配了一个CPU , 真正地同时执行, 这是后话了。

线程

这时候旺财在管理系统已经有了界面,还能访问网络,每当它联网的时候(这也是个非常非常耗时的操作),就得把CPU让给小强。

即使旺财再次被调度执行,由于网络数据还没有返回,他必须等待,什么事情都做不了,在人类看来,界面根本无法操作,旺财不响应了! 气得人类经常把旺财kill掉。

旺财心里苦,他很纳闷小强怎么就没有问题,小强不是要读写硬盘吗? 那也是很慢的操作啊。

小强说:“你傻啊,内部只有一个执行的流程,一遇到耗时的操作就得等待,你看看我,内部搞了两个执行流程(线程),一个用来读写硬盘(T1),另外一个处理界面(T2)。我和操作系统商量好了,如果T1在读写硬盘, 就可以调度我的T2来执行,这样界面至少还可以操作。 ”

旺财觉得很有意思,也采用了类似办法。

于是,一个进程中至少有一个执行的流程(主线程),也可以开启新的执行流程(线程)。

线程变成了最小的调度单位。

协程

这一天,旺财被一个叫做生产者和消费者的问题折腾地死去活来,两个线程,一个线程向队列中放数据,另外一个从队列中取数据,处理起两个线程的协作就显得很麻烦,不但需要加锁,还得做好线程的通知和等待。

正在感慨多线程编程之难的时候, 旺财震惊地发现,小强用了一个极为简单的办法把生产者,消费者问题给解决了。

这个方法的代码如下:

# 生产者
def producer(c):
    #其他代码
    while True:
        value = ...生成数据...
        c.send(value)

# 消费者
def consumer():
    #其他代码
    while True:
        value = yield
        print(value)

c = consumer()
producer(c)

“这…这怎么执行啊,那个yield是怎么回事?” 旺财表示不解。

“简单啊,你看那个生产者,是不是向消费者发送了数据? ” 小强说。

“对啊,然后呢,生产者发送了数据以后,会马上进行下一轮循环吗?”

“这就是关键所在了,”小强说,“ 它们是这么执行的:”

1.生产者发送数据,暂停运行,不进行下一轮循环
2.消费者其实一直在value = yield 那里等待,直到数据到来,现在数据来了,取出处理(value就是生产者发送过来的数据)。
3.消费者在循环中再次yield, 暂停执行。
4.生产者继续下一轮的循环,生成新的消息,发送给消费者。

旺财觉得很吃惊,小强竟然可以让一个正在执行的程序暂停,他不由得问道:“你这个暂停是真的停止了了,还是说只是像Java的yield那样,让出CPU进入了就绪状态? 等待下次调度运行?”

“是真的暂停了,程序就停在那里,等待运行控制权从对方那里转移过来。”

“这不是操作系统干的事情吗? ” 旺财更加吃惊了。

“正是这样,” 小强得意地说:“我打算把类似生产者,消费者这样的代码称为‘协程’, 这个协程有个重要的特点,就是完全被我所调度和掌控, 不用操作系统介入。”

“这个协程和线程似乎很像啊。每次协程停止执行的时候,也得保存现场,要不然没法恢复执行。” 旺财说。

“是啊,只是他们比线程更加轻量级,操作系统内核不用参与,相当于用户态线程了,协程的开销极小,可以轻松地创建大量的协程来做事情。 对了,也许你注意到了,我这两个协程是’合作式’的,它们两个同一时刻只能有一个在运行。 实际上,我在底层可以用一个线程去执行这两个协程。 ”

旺财表示同意:“不错,既然两个程序可以’合作’,那就不用加锁了,也不用在代码里写什么wait和notify了,在程序层面,可以用同步的方式实现异步的功能了! 代码很清晰,我也搞个协程来玩玩吧!”

原文地址:https://www.cnblogs.com/skycto/p/11470207.html

时间: 2024-08-26 14:12:53

一个故事讲完进程、线程和协程(操作系统基础知识)的相关文章

(转)一个故事讲完https

(转)一个故事讲完https 2 1  序言 今天来聊一聊https 安全传输的原理. 在开始之前,我们来虚构两个人物, 一个是位于中国的张大胖(怎么又是你?!), 还有一个是位于米国的Bill (怎么还是你?!). 这俩哥们隔着千山万水,通过网络联系上了, 两个人臭味相投,聊得火热. 此时正值米国大选, 张大胖亲切地"致电"Bill, 对米国总统大选的情况表示强烈地关注. Bill则回电说谢谢关心米国人的事情我们米国人自己做主,不用你们歪果仁瞎操心...... 张大胖继续"

帮你搞懂Python进程,线程与协程

本文参考原文-http://bjbsair.com/2020-03-22/tech-info/4425/在操作系统中,每一个独立运行的程序,都占有 操作系统 分配的资源,这些程序中间互不干涉,都只负责运行自己的程序代码,这就是进程. 但是当操作系统频繁的创建销毁进程时,大量的系统资源被浪费在创建和销毁的过程中.而随着多核心 cpu 的出现,线程也逐渐代替了进程,成为了操作系统 可以独立运行的基本单位. 当进程不是多线程程序时,存在于进程当中的唯一线程,便是进程本身运行的代码块. 而当多线程出现在

一个故事讲完https

本文转自微信号:coderising   码农翻身 在开始之前,我们来虚构两个人物, 一个是位于中国的张大胖(怎么又是你?!), 还有一个是位于米国的Bill (怎么还是你?!). 这俩哥们隔着千山万水,通过网络联系上了, 两个人臭味相投,聊得火热. 此时正值米国大选, 张大胖亲切地"致电"Bill, 对米国总统大选的情况表示强烈地关注. Bill则回电说谢谢关心米国人的事情我们米国人自己做主,不用你们歪果仁瞎操心...... 张大胖继续"致电"说其实我们支持特朗普

Day9 - 进程、线程、协程篇(二)

本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko SSH Twsited网络框架 协程(单线程下实现多并发的效果) 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.(CPU不认识协程,是用户自己操作的) 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候

Python 中的进程、线程、协程、同步、异步、回调

进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 在刚刚结束的 PyCon2014 上海站,来自七牛云存储的 Python 高级工程师许智翔带来了关于 Python 的分享<Python中的进程.线程.协程.同步.异步.回调>. 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说明一点术语.当我们说"上下文"的时候,指的是程序在执行中的一个状态.通常我们会用调用栈来表示这个状

Python—进程、线程、协程

一.线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 方法: start            线程准备就绪,等待CPU调度 setName      设置线程名称 getName      获取线程名称 setDaemon   把一个主进程设置为Daemon线程后,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论有没执行完成,都会停止 j

Python之进程、线程、协程篇

本章内容: 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 线程 Threading用于提供线程相关的操作.线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. threading 模块建立在 _thread 模块之上.thread 模块以低级.原始的方式来处理和控制线程,而 threading

Python(八)进程、线程、协程篇

本章内容: 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 线程 Threading用于提供线程相关的操作.线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. threading 模块建立在 _thread 模块之上.thread 模块以低级.原始的方式来处理和控制线程,而 threading

python之进程、线程、协程的调度原理

进程.线程和协程的调度和运行原理总结. 进程.线程的调度策略介绍 linux的操作系统详细调度策略可参考:http://blog.csdn.net/gatieme/article/details/51872659 linux中的进程主要有三种调度策略: 优先级调度:将进程分为普通进程和实时进程: 先进先出(队列)调度:实时进程先创建的先执行,直到 轮转调度(时间片):达到一定的CPU执行时间后强制切换: 多进程程序的调度其实还是线程的调度,线程才是CPU调度的基本单位:在同一个进程内线程切换不会