想进BAT?负载均衡必须懂!从入门到实操,共享娱乐棋牌注册送38老鸟带你走上高并发架构之路,详情点击>>>
0
51CTO首页 技术频道 51CTO旗下网站 地图
CTO俱乐部 学院 论坛 博客 下载 更多

我的帖子

个人中央

设置

  发新话题
很久当初,有两个程序,暂且称他们旺财和小强吧。
旺财和小强这两个程序都很长,每个都有十几万行。 他们两个的人生价值就是到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是怎么回事?”  旺财表示不解。
“简单啊,你看那个出产者,是不是向消费者发送了数据? ” 小强说。
“对啊,然后呢,出产者发送了数据将来,会眼看进行下一轮循环吗?”
“这就是关键所在了,”小强说,“ 它们是这么执行的:”
  • 出产者发送数据,暂停运行,不进行下一轮循环
  • 消费者其实一直在value = yield 那里等待,直到数据到来,现在数据来了,取出解决(value就是出产者发送过来的数据)。
  • 消费者在循环中再次yield, 暂停执行。
  • 出产者继续下一轮的循环,生成新的信息,发送给消费者。


旺财觉得很震惊,小强居然可以让一个正在执行的程序暂停,他不由得问道:“你这个暂停是真的停止了了,还是说只是像Java的yield那样,让出CPU进入了就绪状态? 等待下次调度运行?”
“是真的暂停了,程序就停在那里,等待运行控制权从对方那里转移过来。”
“这不是操作系统干的事情吗? ” 旺财更加震惊了。
“正是这样,” 小强自豪地说:“我准备把宛若出产者,消费者这样的代码称为‘协程’, 这个协程有个重要的特点,就是完整被我所调度和掌控, 不用操作系统介入。”
“这个协程和线程宛若很像啊。每次协程停止执行的时候,也得保存现场,要不然没法恢复执行。” 旺财说。
“是啊,只是他们比线程更加轻量级,操作系统内核不用参与,相当于用户态线程了,协程的开销极小,可以轻盈地创建大量的协程来做事情。 对了,大概你留意到了,我这两个协程是'合作式'的,它们两个同一时刻只能有一个在运行。 实际上,我在底层可以用一个线程去执行这两个协程。  ”
旺财表示同意:“不错,既然两个程序可以'合作',那就不用加锁了,也不用在代码里写什么wait和notify了,在程序层面,可以用同步的方式实现异步的性能了! 代码很清晰,我也搞个协程来玩玩吧!”



赞赞赞




标注转载出处




引用:
原帖由 叮叮丁丁 于 2018-6-8 07:17 发表
标注转载出处

忘了。。想不起哪里来的了。。。



宝剑厉不猛烈,要看它的主人是谁,不信来PHP版块看看~!
引用:
原帖由 七彩极 于 2018-06-06 17:38 发表
一个故事讲完进程、线程和协程
不错



引用:
原帖由 七彩极 于 2018-06-06 17:38 发表
一个故事讲完进程、线程和协程





引用:
原帖由 叮叮丁丁 于 2018-6-8 07:17 发表
标注转载出处

差点儿以为原创是你~



引用:
原帖由 咖啡 于 2018-6-12 14:01 发表

差点儿以为原创是你~
nono,it's not me



就喜欢看你的贴~



真的不错,通俗易懂,还很简单记住。



‹‹ 上一贴:你认为自己是Python的哪个级别了?   |   下一贴:一次Scrapy框架爬取淘宝商品信息的尝试 ... ››
  发新话题
敏捷回答主题
关于我们 | 诚聘英才 | 联系我们 | 网站大事 | 友情链接 |建议反馈 | 网站地图
Copyright©2005-2018 51CTO.COM
本论坛言论纯属发布者个人建议,不代表51CTO网站立场!如有疑义,请与管理员联系:邮箱