进程、线程和协程

进程的定义:

进程,是计算机中已运行程序的实体。程序本身只是指令、数据及其组织形式的描述,进程才是程序的真正运行实例。

线程的定义:

操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。

进程和线程的关系:

一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

CPU的最小调度单元是线程不是进程,所以单进程多线程也可以利用多核CPU.

协程的定义:

协程通过在线程中实现调度,避免了陷入内核级别的上下文切换造成的性能损失,进而突破了线程在IO上的性能瓶颈。

协程和线程的关系

协程是在语言层面实现对线程的调度,避免了内核级别的上下文消耗。

python协程与调度

Python的协程源于yield指令。yield有两个功能:

yield item用于产出一个值,反馈给next()的调用方。

作出让步,暂停执行生成器,让调用方继续工作,直到需要使用另一个值时再调用next()。

import asyncio

async def compute(x, y):

print("Compute %s + %s ..." % (x, y))

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))

loop = asyncio.get_event_loop()

tasks = [print_sum(1, 2), print_sum(3, 4)]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

协程是对线程的调度,yield类似惰性求值方式可以视为一种流程控制工具,

实现协作式多任务,在Python3.5正式引入了 async/await表达式,使得协程正式在语言层面得到支持和优化,大大简化之前的yield写法。

线程是内核进行抢占式的调度的,这样就确保了每个线程都有执行的机会。

而 coroutine 运行在同一个线程中,由语言的运行时中的 EventLoop(事件循环)来进行调度。

和大多数语言一样,在 Python 中,协程的调度是非抢占式的,也就是说一个协程必须主动让出执行机会,其他协程才有机会运行。

让出执行的关键字就是 await。也就是说一个协程如果阻塞了,持续不让出 CPU,那么整个线程就卡住了,没有任何并发。

PS: 作为服务端,event loop最核心的就是IO多路复用技术,所有来自客户端的请求都由IO多路复用函数来处理;作为客户端,event loop的核心在于利用Future对象延迟执行,并使用send函数激发协程,挂起,等待服务端处理完成返回后再调用CallBack函数继续下面的流程

Go的协程

Go天生在语言层面支持,和Python类似都是采用了关键字,而Go语言使用了go这个关键字,可能是想表明协程是Go语言中最重要的特性。

go协程之间的通信,Go采用了channel关键字。

Go实现了两种并发形式:

多线程共享内存。如Java或者C++等在多线程中共享数据(例如数组、Map、或者某个结构体或对象)的时候,通过锁来访问.

Go语言特有的,也是Go语言推荐的:CSP(communicating sequential processes)并发模型。

package main

import (

"fmt"

)

//Go 协程(goroutines)和协程(coroutines)

//Go 协程意味着并行(或者可以以并行的方式部署),协程一般来说不是这样的

//Go 协程通过通道来通信;协程通过让出和恢复操作来通信

// 进程退出时不会等待并发任务结束,可用通道(channel)阻塞,然后发出退出信号

func main() {

jobs := make(chan int)

done := make(chan bool) // 结束标志

go func() {

for {

j, more := <-jobs // 利用more这个值来判断通道是否关闭,如果关闭了,那么more的值为false,并且通知给通道done

fmt.Println("----->:", j, more)

if more {

fmt.Println("received job", j)

} else {

fmt.Println("end received jobs")

done <- true

return

}

}

}()

go func() {

for j := 1; j <= 3; j++ {

jobs <- j

fmt.Println("sent job", j)

}

close(jobs) // 写完最后的数据,紧接着就close掉

fmt.Println("close(jobs)")

}()

fmt.Println("sent all jobs")

<-done // 让main等待全部协程完成工作

}

通过在函数调用前使用关键字 go,我们即可让该函数以 goroutine 方式执行。goroutine 是一种 比线程更加轻盈、更省资源的协程。

Go 语言通过系统的线程来多路派遣这些函数的执行,使得 每个用 go 关键字执行的函数可以运行成为一个单位协程。

当一个协程阻塞的时候,调度器就会自 动把其他协程安排到另外的线程中去执行,从而实现了程序无等待并行化运行。

而且调度的开销非常小,一颗 CPU 调度的规模不下于每秒百万次,这使得我们能够创建大量的 goroutine,

从而可以很轻松地编写高并发程序,达到我们想要的目的。 ---- 某书

协程的4种状态

Pending

Running

Done

Cacelled

和系统线程之间的映射关系

go的协程本质上还是系统的线程调用,而Python中的协程是eventloop模型实现,所以虽然都叫协程,但并不是一个东西.

Python 中的协程是严格的 1:N 关系,也就是一个线程对应了多个协程。虽然可以实现异步I/O,但是不能有效利用多核(GIL)。

而 Go 中是 M:N 的关系,也就是 N 个协程会映射分配到 M 个线程上,这样带来了两点好处:

多个线程能分配到不同核心上,CPU 密集的应用使用 goroutine 也会获得加速.

即使有少量阻塞的操作,也只会阻塞某个 worker 线程,而不会把整个程序阻塞。

PS: Go中很少提及线程或进程,也就是因为上面的原因.

两种协程对比:

async是非抢占式的,一旦开始采用 async 函数,那么你整个程序都必须是 async 的,不然总会有阻塞的地方(一遇阻塞对于没有实现异步特性的库就无法主动让调度器调度其他协程了),也就是说 async 具有传染性。

Python 整个异步编程生态的问题,之前标准库和各种第三方库的阻塞性函数都不能用了,如:requests,redis.py,open 函数等。所以 Python3.5后加入协程的最大问题不是不好用,而是生态环境不好,历史包袱再次上演,动态语言基础上再加上多核之间的任务调度,应该是很难的技术吧,真心希望python4.0能优化或者放弃GIL锁,使用多核提升性能。

goroutine 是 go 与生俱来的特性,所以几乎所有库都是可以直接用的,避免了 Python 中需要把所有库重写一遍的问题。

goroutine 中不需要显式使用 await 交出控制权,但是 Go 也不会严格按照时间片去调度 goroutine,而是会在可能阻塞的地方插入调度。goroutine 的调度可以看做是半抢占式的。

Do not communicate by sharing memory; instead, share memory by communicating.(不要以共享内存的方式来通信,相反,要通过通信来共享内存) -- CSP并发模型

扩展与总结

erlang和golang都是采用了CSP(Communicating Sequential Processes)模式(Python中的协程是eventloop模型)

但是erlang是基于进程的消息通信,go是基于goroutine和channel的通信。

Python和Go都引入了消息调度系统模型,来避免锁的影响和进程/线程开销大的问题。

协程从本质上来说是一种用户态的线程,不需要系统来执行抢占式调度,而是在语言层面实现线程的调度。

因为协程不再使用共享内存/数据,而是使用通信来共享内存/锁,因为在一个超级大系统里具有无数的锁,

共享变量等等会使得整个系统变得无比的臃肿,而通过消息机制来交流,可以使得每个并发的单元都成为一个独立的个体,

拥有自己的变量,单元之间变量并不共享,对于单元的输入输出只有消息。

开发者只需要关心在一个并发单元的输入与输出的影响,而不需要再考虑类似于修改共享内存/数据对其它程序的影响。

python中协程与函数的区别_python 协程与go协程的区别相关推荐

  1. python中的内置函数怎么学_python内部函数学习(九)

    python提供了很多的内置函数,这些内置的函数在某些情况下,可以起到很大的作用,而不需要专门去 写函数实现XX功能,直接使用内置函数就可以实现,下面分别来学习内置函数的使用和案例代码. 1.abs( ...

  2. python中如何查一个函数的用法_Python常见内置函数用法(三)

    本文作者:孙雪丽 文字编辑:周聪聪 技术总编:张学人重大通知!!!2019年6月22日至24日在河南郑州举行Stata编程技术特别训练营,招生工作已经圆满结束.另外爬虫俱乐部将于2019年7月5日至7 ...

  3. python中的内置函数返回元素_Python内置函数_________用来返回数值型序列中所有元素之和。...

    已知向量m=(3sinx4,1),n=(cosx4,cos2x4),记f(x)=m?n,(1)求f(x)的值域和单调递增区间:(2)在△ABC中,角A.B.C的 真空度=绝对压强-大气压强 () 在连 ...

  4. Python中str()与repr()函数的区别——repr() 的输出追求明确性,除了对象内容,还需要展示出对象的数据类型信息,适合开发和调试阶段使用...

    Python中str()与repr()函数的区别 from:https://www.jianshu.com/p/2a41315ca47e 在 Python 中要将某一类型的变量或者常量转换为字符串对象 ...

  5. 【Python】Python中str()和repr()函数的区别

    作用 在 Python 中要将某一类型的变量或者常量转换为字符串对象通常有两种方法,即 str() 或者 repr() . 区别与使用 参考文章:Python 中 str() 和 repr() 函数的 ...

  6. python函数分几种_简单了解Python中的几种函数

    python是支持多种范型的语言,可以进行所谓函数式编程,其突出体现在有这么几个函数: filter.map.reduce.lambda.yield lambda lambda函数的使用方法:在lam ...

  7. python items函数用法,Python中dictionary items()系列函数的用法实例

    本文实例讲述了Python中dictionary items()系列函数的用法,对Python程序设计有很好的参考借鉴价值.具体分析如下: 先来看一个示例: import html # availab ...

  8. Python中sort和sorted函数代码解析

    Python中sort和sorted函数代码解析 本文研究的主要是Python中sort和sorted函数的相关内容,具体如下. 一.sort函数 sort函数是序列的内部函数 函数原型: L.sor ...

  9. python中的且和或怎么表示_python中逻辑与或(and、or)和按位与或异或(、|、^)区别...

    按位与或(&.|.^):按照二进制进行逻辑运算 例如:数字换成二进制,各自位上的0/1进行逻辑运算,得到的结果转换为数字 3 & 2 =0111 & 0010 =0010 =2 ...

  10. python平方数迭代器_对python中的高效迭代器函数详解

    python中内置的库中有个itertools,可以满足我们在编程中绝大多数需要迭代的场合,当然也可以自己造轮子,但是有现成的好用的轮子不妨也学习一下,看哪个用的顺手~ 首先还是要先import一下: ...

最新文章

  1. python将变量a全部变成大写字母_每天一个Python知识点:只用一招就将所有的英文单词首字母变成大写...
  2. 别再用kill -9关闭程序了......
  3. Windows下编译 Hadoop
  4. ecs服务器配置git_阿里云 ECS服务器(CentOS 7)安装和使用Gitlab教程
  5. 「浏览器插件」非常好用的JSON-View
  6. 【算法】逆波兰式(后缀表达式)的计算 中缀表达式转后缀表达式(逆波兰式)
  7. 软件更新 正在连接至服务器,正在联系iphone软件更新服务器【操作指南】
  8. 编译Android源码致命错误解决方案
  9. flink sql运用入门
  10. 织梦采集插件-简单好用织梦采集插件
  11. mtk 充电出错问题
  12. ENVI监督分类错误:分离度为0.00000解决办法
  13. python 全栈开发,Day122(人工智能初识,百度AI)
  14. zabbix4.0 zabbix-server.service never wrote its PID file. Failing.
  15. c语言字母圣诞树,如何用C语言画一个“圣诞树”.pdf
  16. 微信群裂变引流效果怎么样?微信社群引流怎么操作?
  17. Suse12离线安装docker
  18. 数据库高可用架构 - pxc
  19. 通过vue-codemirror和CodeMirror将代码编辑器添加到web项目中
  20. A Review on Deep Learning Applications in Prognostics and Health Management (翻译)

热门文章

  1. Redhat的Linux产品版本AS/ES/WS的联系与区别
  2. 安全四部曲之一---***工具简单使用
  3. js实现连接的两种放法
  4. Spring AOP 代理模式
  5. java uuid 线程安全_java – 在多线程应用程序中生成相同的UUID
  6. 计算机应用基础精品课程申报表,《计算机应用基础》精品课程申报书(修改意见)...
  7. JDBC笔记-李伟杰版
  8. 【机器学习】opencv-摄像头中的人脸采集
  9. CCF推荐各种国际学术会议和期刊目录
  10. java递归空瓶换饮料_问题描述:一次买n瓶可乐,k个空瓶可以换一瓶饮料,那么一共能喝多少瓶饮料? | 学步园...