请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于线程和协程的一个疑问

bobby老师你好,像Java项目中,一个用户发起一个请求,就相当于起了一个线程去处理这个用户的请求,那在go中,是起的线程还是协程呢?

后续的课程中,多协程的开发涉及的多吗?什么样的项目,对于多协程或多进程是用的比较多的?

正在回答

1回答

    你的这个问题很好,协程是多线程以后发展出来的,也就是现目前所有的主流语言都是多线程上的产物,包括java,python,js、php、c++等,多线程基本上都回对应于计算机本身的一个线程,比如你开一个python线程,实际上这个线程就是去让操作系统开启一个线程,java也是一样的,但是问题是----线程开销大啊!!!,主要体现在两个点上:

    1. 内存占用大

    2. 切换费时

    所以对于比如同时维护10000个连接,基本上单机很难做到,所以协程就出来了,协程可以这样简单理解:一个协程就像一个函数一样(实际上python可以这样简单理解,但是go不一样,不过大概思路就是这样的),一个进程维护10000个函数调用那简直是非常easy的,但是一个函数无法像线程一样切换啊,像线程一样维护调用栈啊,所以协程就出现了- 将函数封装一下变成既可以像线程一样维护也可以像函数一样由程序自己控制调用的机制就出现了-协程,但是另一个问题出现了 -  协程写法如何和线程的写法区别开来啊!!!

    这个时候go语言优势体现出来了---go是新语言,可以抛弃线程,就没有所谓的将线程和协程区别开来的两种写法了,所以go语言作为新语言是没有历史包袱的--- 不需要兼容线程写法和协程写法,但是其他语言就痛苦了。

    python、js、java都面临着这种历史包袱,即使你提供了协程,但是你还得兼容两种写法----因为你已有的大量库都是基于线程的,你不能放弃这些库啊,你放弃了谁还用你啊,所以python和js都搞出了async好await语法用于区别两种情况,java更麻烦了-你要使用协程你得使用netty这样的库,java语法本身目前还不支持两种写法,但是这两种写法就让很多初学者懵逼了-async和await到底是什么鬼,怎么区别,所以就将语法本身变复杂了,这也就是一种语言如果本身选项太多,初学者痛苦

    go就没有这个问题,因为go没有历史包袱,因为go一开始就只支持协程,因为不用支持线程,所以go发展起来的所有的库都是支持协程的,这也就回答了你的问题-什么时候选用协程,什么时候选用线程:

    1. 能使用协程的就使用协程,因为并发高,但是协程的生态在其他语言中是个头疼的问题,因为所有的有多线程的语言都是线程的生态系统最强大,所以你如果选用了协程可能你得找到对应的生态库,

    2. go语言不用纠结,因为本身没有多线程的说法,随便用

最后提醒一下: go语言本身是goroutine,但是底层对于这么多goroutine的调度维护仍然是使用了操作系统的线程维护的,也就是本质上仍然是几万个goroutine实际上也就是那么几十几百个操作系统的线程在维护而已,只不过不用频繁的启动大量线程和切换大量的线程了而已,具体原理建议百度 go语言的gmp调度模型



3 回复 有任何疑惑可以回复我~
  • 提问者 精慕门4214220 #1
    那我是不是可以这样理解一下,协程是基于线程的基础之上的,go程序跑起来了,那本身得是一个进程吧,main函数我就当它是一个线程,主线程,来一次请求,主线程开一个协程去处理,一个线程可以随意处理n多个协程,当一个(线程)无法再去开启额外多的协程的时候,操作系统可能自己会去起另外一个(线程),然后由这个(线程)去开启协程处理用户的请求,我之前在知乎上看过gmp,大概就是用地鼠、砖头、推车来做比喻,当时没有太理解
    回复 有任何疑惑可以回复我~ 2020-12-15 11:53:27
  • bobby 回复 提问者 精慕门4214220 #2
    说的基本上正确, gmp理解起来确实比较麻烦
    回复 有任何疑惑可以回复我~ 2020-12-16 13:31:04
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信