go语言协程实现机制 go语言如何限制协程数量( 三 )


我这里只是根据自己的理解进行了简单的介绍,想要详细了解有关GMP的底层原理可以去看Go调度器 G-P-M 模型的设计者的文档或直接看源码
参考:()
()
协程与异步IO协程,又称微线程,纤程 。英文名 Coroutine。Python对协程的支持是通过 generator 实现的 。在generator中,我们不但可以通过for循环来迭代 , 还可以不断调用 next()函数 获取由 yield 语句返回的下一个值 。但是Python的yield不但可以返回一个值 , 它还可以接收调用者发出的参数 。yield其实是终端当前的函数 , 返回给调用方 。python3中使用yield来实现range , 节省内存,提高性能,懒加载的模式 。
asyncio是Python3.4 版本引入的 标准库 ,直接内置了对异步IO的支持 。
从Python3.5 开始引入了新的语法 async 和 await,用来简化yield的语法:
import asyncio
import threading
async def compute(x, y):
print("Compute %s + %s ..." % (x, y))
print(threading.current_thread().name)
await asyncio.sleep(x + y)
return x + y
async def print_sum(x, y):
result = await compute(x, y)
print("%s + %s = %s" % (x, y, result))
print(threading.current_thread().name)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
tasks = [print_sum(1, 2), print_sum(3, 4)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
线程是内核进行抢占式的调度的,这样就确保了每个线程都有执行的机会 。而 coroutine 运行在同一个线程中,由语言的运行时中的EventLoop(事件循环) 来进行调度 。和大多数语言一样,在 Python 中,协程的调度是非抢占式的 , 也就是说一个协程必须主动让出执行机会,其他协程才有机会运行 。
让出执行的关键字就是 await 。也就是说一个协程如果阻塞了 , 持续不让出 CPU,那么整个线程就卡住了,没有任何并发 。
PS: 作为服务端,event loop最核心的就是IO多路复用技术,所有来自客户端的请求都由IO多路复用函数来处理;作为客户端 , event loop的核心在于利用Future对象延迟执行,并使用send函数激发协程,挂起,等待服务端处理完成返回后再调用CallBack函数继续下面的流程
Go语言的协程是 语言本身特性 ,erlang和golang都是采用了CSP(Communicating Sequential Processes)模式(Python中的协程是eventloop模型) , 但是erlang是基于进程的消息通信,go是基于goroutine和channel的通信 。
Python和Go都引入了消息调度系统模型,来避免锁的影响和进程/线程开销大的问题 。
协程从本质上来说是一种用户态的线程 , 不需要系统来执行抢占式调度,而是在语言层面实现线程的调度。因为协程 不再使用共享内存/数据 ,而是使用 通信 来共享内存/锁 , 因为在一个超级大系统里具有无数的锁 , 共享变量等等会使得整个系统变得无比的臃肿,而通过消息机制来交流 , 可以使得每个并发的单元都成为一个独立的个体 , 拥有自己的变量 , 单元之间变量并不共享,对于单元的输入输出只有消息 。开发者只需要关心在一个并发单元的输入与输出的影响,而不需要再考虑类似于修改共享内存/数据对其它程序的影响 。
为什么go语言适合开发网游服务器端前段时间在golang-China读到这个贴:
个人觉得golang十分适合进行网游服务器端开发,写下这篇文章总结一下 。
从网游的角度看:
要成功的运营一款网游,很大程度上依赖于玩家自发形成的社区 。只有玩家自发形成一个稳定的生态系统,游戏才能持续下去,避免鬼城的出现 。而这就需要多次大量导入用户,在同时在线用户量达到某个临界点的时候 , 才有可能完成 。因此 , 多人同时在线十分有必要 。

推荐阅读