由线程遗留下的问题:GIL导致多个线程不能真正的并行,CPython中多个线程不能并行

单线程实现并发:切换+保存状态

  第一种方法:使用yield,yield可以保存状态。yield的状态保存与操作系统保存线程状态很像,但是yield是代码级控制的,更更轻量级。

# 两个计算任务一个采用生成器切换并发执行  一个直接串行调用
import time
def task1():
a =
for i in range():
a += i
yield def task2():
g = task1()
b =
for i in range():
b +=
next(g)
s = time.time()
task2()
print("并发执行时间",time.time()-s) # 单线程下串行执行两个计算任务 效率反而比并发高 因为并发需要切换和保存
def task1():
a =
for i in range():
a += i
def task2():
b =
for i in range():
b +=
s = time.time()
task1()
task2()
print("串行执行时间",time.time()-s)

可以看出,对于纯计算任务而言,单线程并发反而使效率降低。而且使用yield来切换使得代码结构混乱。

  第二种方法:使用greenlet模块,仅仅是对yield在封装。依然不能对检测IO操作。

import greenlet
def task1(name):
print("%s task1 run1" % name)
g2.switch(name) # 切换至任务2
print("task1 run2")
g2.switch() # 切换至任务2 def task2(name):
print("%s task2 run1" % name)
g1.switch() # 切换至任务1
print("task2 run2") g1 = greenlet.greenlet(task1)
g2 = greenlet.greenlet(task2)
g1.switch("jerry") # 为任务传参数

  第三种办法:协程

  协程: 指的是一个线程完成并发执行,协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的 

  强调:
  1. python的线程始于内核级别的,即由操作系统控制调度(遇到IO或执行事件过长就会被迫交出CPU执行权限,切换到其他线程)
  2. 单线程内开启协程,一旦遇到IO,就会从应用程序级别控制切换,以此来提升效率

  优点:

  1. 协程的切换开销更小,属于程序级别的切换,更加轻量级

  2. 单线程内就可以实现并发的效果,最大限度的利用CPU

  缺点:

  1. 协程本质是单线程并发,无法利用多核,可以是一个程序开多个进程,每个进程内开启多个线程,每个线程内开启协程

  2. 一旦协程遇到阻塞,将会阻塞整个线程

  

  在CPython中,如果是计算密集型,使用协程是无法提高效率,反而因为切换任务导致效率较低,只能靠进程。IO密集型 多线程会比多进程效率高,因为多线程开销比多进程小的多。

  使用模块:gevent,gevent既可以单线程实现并发,又可以检测IO操作
import gevent
import time
from gevent import monkey # 导入monkey补丁
monkey.patch_all() # 打补丁 def task1():
print("task1 run")
# gevent.sleep()
time.sleep()
print("task1 over") def task2():
print("task2 run")
# gevent.sleep()
time.sleep()
print("task2 over") g1 = gevent.spawn(task1)
g2 = gevent.spawn(task2)
# g1.join()
# g2.join()
gevent.joinall([g1,g2])
  需要注意:
  1. 协程执行时必须对协程对象调用join函数(join让主线程等待协程任务完成,因为主线程一旦结束,协程任务就不执行了。反过来说 要保证协程任务正常执行结束 必须保证主线程没有结束)
  2. 如果有多个任务,随便调用哪一个的join都会并发执行所有任务,但是需要注意如果有一个存在IO操作的任务没有被join,该任务将无法正常执行完毕。
  3. monkey补丁的原理,把原始的阻塞模块替换为修改后的非阻塞模块,来实现IO自定切换,所以打补丁的位置尽量要放在导入阻塞模块之前

python并发编程之协程知识点的更多相关文章

  1. 32 python 并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  2. 四 python并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  3. python并发编程之协程(实践篇)

    一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 对于单线程下,我们不可避免程序中出现io操作,但如果我们 ...

  4. 第十篇.5、python并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

  5. 第 12 章 python并发编程之协程

    一.引子 主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只用一个)情况下实现并发,并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作 ...

  6. 37、python并发编程之协程

    目录: 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本节的主题是基于单线程来 ...

  7. python 并发编程之协程

    一.协程 协程: 单线程下的并发,又称 微线程.协程是一种用户态的的轻量级线程,即协程是由用户程序自己控制调度的. ​ 协程的本质就是在单线程下,由用户自己控制一个任务,遇到 io 阻塞就切换另外一个 ...

  8. python并发编程之协程

    ---恢复内容开始--- 一.join方法 (1)开一个主线程 from threading import Thread,currentThread import time def walk(): p ...

  9. python全栈开发从入门到放弃之socket并发编程之协程

    一.为什么会有协程 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情 ...

随机推荐

  1. 学JAVA第十三天,方法、方法重载及构造函数

    今天终于不讲狗跳楼的问题了,今天讲了方法,方法重载及构造函数及构造函数重载的课程了. 这里说了有参好无参的,下面讲构造函数重载和方法重载. 其实,这上面写的这些方法,就相当一个模板.想要快速做出产品就 ...

  2. 通用mapper认识和用法

    目录 0. 认识 1. 导包 2. mybatis的config文件:mybatis-mapper-config.xml 3. spring与mybatis整合配置文件:mybatis.xml 4. ...

  3. ajax验证用户名是否存在

    jsp页面 <head> <script type="text/javascript" src="js/register.js">< ...

  4. PHP数字金额转换大写金额

    早些年做CRM用到的一个金额转换函数,今天从旧项目中拿出来记录一下.金额转换的函数方法有很多,都很不错.不过这个是小崔刚工作的时候写的一个转换函数,多少还是有点纪念意义.如有问题请朋友们指出,小崔及时 ...

  5. java工作流引擎Jflow父子流程demo

    关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow  .net开源工作流 定义 一个流程A的一个节点,因工作的需要调起另外的流程B,A就叫父流程,B就叫子流程.如果流 ...

  6. servlet与jsp篇(一)$.ajax交互

    servlet其实是利用java类编写的服务器端应用程序,他的生命周期可以分为三个阶段:初始化阶段.运行阶段和消亡阶段; jsp页面实质上是一个HTML页面,但他包含了用户产生动态网页内容的java代 ...

  7. 七、Android动画

    Android的动画可以分为三种:View动画.帧动画和属性动画,帧动画也属于View动画的一种,只不过它和平移.旋转等常见的View动画在表现形式上略有不同而已. 1.View动画 平移动画:Tra ...

  8. typescript中的接口

    说到接口:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用.接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心 ...

  9. 深入浅出KNN算法(二) sklearn KNN实践

    姊妹篇: 深入浅出KNN算法(一) 原理介绍 上次介绍了KNN的基本原理,以及KNN的几个窍门,这次就来用sklearn实践一下KNN算法. 一.Skelarn KNN参数概述 要使用sklearnK ...

  10. redis数据库安装 redis持久化及主从复制

    ----------------------------------------安装redis-5.0.4---------------------------------------- wget h ...