我去,第一个这种简单问题都需要详细解释。我再用尽可能简单的语言重新描述一下
现在假设线程t执行了一个协程c1,协程c1内部有若干操作,其中有1次磁盘同步blocking写入,写入之后更新ui。很常见的场景,对吧
当线程t执行到第一次磁盘写入的时候,按照你之前的Jave Green thread说法,下面是编译器或运行时会隐式把这个同步写入转换成异步写入,异步写入开始之后,协程c1挂起,释放线程t。
那么下面问题就来了,线程t下面要干什么?
1.闲着等c1。那这种情况用协程做什么?直接开线程就好了
2.调度协程c2。假设c2需要执行10s。在执行到第五秒的时候,c1异步io执行完毕,需要调度。
都是选择2.那么新问题又来了,此时怎么调度c1?
gfkid看明白了我在说什么,他的答复是
“那可能确实会等待了吧,也可能会抢占该线程,把当前运行的goroutine调度到其它可用的线程 ”
这个就是问题,在实践中大家没有一个完美的方案,在这里要做tradeoff
抢占这点我是怀疑的,因为运行时不知道该不该抢占,而且如果此时是10个协程等待回来,谁抢谁的是很难确定的,胡乱调度会出问题。
所以目前我不知道有带CO-routine的语言,不管是几代协程,在此处是抢占
等待会影响吞吐,没有一个后台语言会接受等待,都是直接找个空闲线程t2继续执行c1
而c1如果在t2上执行,后面的ui操作,如果发现当前线程不是ui线程t1,会直接异常的。
所以其实没有特别好的办法解决,async对这个问题的解决办法提供两种方式用户自选
而你在说的是“python, javascript 和 c++ 都是手动调度”,这个是不对的
js的选择是“等待”,它是单线程只有这一个选择
c++是用户自己选。用python搞高性能的程序是行为艺术
这个问题更一般的说,是os把一些资源绑定到了线程上,在线程对多个协程调度的时候,对这些资源的访问必然会出现问题要处理。
UI线程是问题最突出的,但还有很多别的比如tls,mutex重入等等一堆问题
go和Green thread我之前当他没有释放线程,没有释放线程他就没有重入问题,但是性能会低下。
你这次非说有,有就带来重入线程问题。问你咋搞的你又说不知道(下面stub的问题)
2、4问题和下面stub问题的是一个问题,你回答我的是怎么怎么很方便,回答他的说,其实你也不知道。
你不知道你吹个Green thread锤子
5懒得和你解释了,今天你在我这的免费知识普及额度已经用光了(其实是我今天打字太多了),以后看机会吧
我回头整理整理回复你的话,这两年教你协程的内容我都快能出本书了
【 在 hgoldfish 的大作中提到: 】
: 1. 因为协程并不天然地在线程间调度。python, javascript 和 c++ 都是手动调度,所以协程在哪个线程里面是确定的。所以直接在协程里面更新 GUI 控件是可以的。
: 2. 碰到阻塞的 IO 操作就重写一个呗。接下来看谁重写的代价比较低了。python gevent 的代价是最低的,正常只要 monkey patch 即可搞定。此外 c++ 还有 libgo 之类的方案也特别低,模拟 go 语言并且 fork system api 很方便。
: 3. go 语言我不知道,但 python 跑在虚拟机上面。greenlet 和 asyncio 的切换成本都特别低,低到只要一两条 python 字节码。你担心个啥性能?java 和 c# 也是跑在虚拟机上面,再怎么牛逼,也没法比 c++20 的协程切换强吧。
: ...................
--
修改:leadu FROM 123.116.219.*
FROM 123.116.219.*