协程

并发编程之协程

流过昼夜 提交于 2020-01-04 05:08:12
目录 协程 什么是协程 线程出现的问题 使用协程的好处 符合什么条件就能称之为协程: 协程的使用场景 Python中对于协程有两个模块,greenlet和gevent。 Greenlet(greenlet的执行顺序需要我们手动控制) gevent(自动切换,由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成) 协程 什么是协程 ​ 在 单个线程下 实现并发效果,在多个任务之间切换。协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置,当程序中存在大量不需要CPU的操作时(IO),适用于协程。 ​ 官方说法:协程称为微线程,就是操作系统级别的线程。是由操作系统来控制调度的。 线程出现的问题 GIL锁 导致多线程无法并行执行,只能并发执行,效率低。但是并发时我们要实现的最终目的(最好并行) 线程出现假死状态 例如tcp服务器,限制了最大线程数量1000,如果第1000个客户有一部分,没有进行任何的操作,而新任务将无法被处理,即使CPU空闲 使用协程的好处 协程有极高的执行效率,因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销 不需要多线程的锁机制,因为只有一个线程 ,不存在同时写变量冲突,在协程中控制共享资源不加锁

day38,线程队列,协程

房东的猫 提交于 2020-01-04 05:08:02
协程和断点上传 线程中的队列 我们经常会遇到这样的一个问题,这里有成千上万条数据,每次需要取出其中的一条数据进行处理,那么引入多线程该怎么进行任务分配? 我们可以将数据进行分割然后交给多个线程去跑,可是这并不是一个明智的做法。在这里我们可以使用队列与线程相结合的方式进行任务分配。 队列线程的思想: 首先创建一个全局共享的队列,队列中只存在有限个元素,并将所有的数据逐条加入到队列中,并调用队列的join函数进行等待。之后便可以开启若干线程,线程的任务就是不断的从队列中取数据进行处理就可以了。 from queue import Queue,LifoQueue,PriorityQueue # 与进程中的Joinablequeue 使用方式一模一样 但是 不具备IPC # q = Queue() # q.put("123") # q.put("456") # print(q.get()) # print(q.get()) # # print(q.get(block=True,timeout=3)) # q.task_done() # q.task_done() # q.join() # print("over") # last in first out 后进先出 先进 后出 模拟堆栈 ====================================================

day33-2 协程

妖精的绣舞 提交于 2020-01-04 05:07:51
目录 协程 单线程实现并发 greenlet模块实现并发 gevent模块实现并发 协程与线程比较 协程 由于GIL锁导致在Cpython中多线程无法并行执行,只能并发执行。而并发实现的原理是切换+保存,那就意味着使用多线程实现并发,就需要为每一个任务创建一个线程 问题一:必然增加了线程创建销毁与切换带来的资源开销。 问题二:高并发情况下,由于任务数量太多导致无法开启新的线程,使得即没有实际任务要执行,也无法创建新线程来处理新任务的情况 所以应想办法避免创建线程带来的问题,同时又能保证并发效果, 协程就是使用单线程来实现多任务并发 单线程实现并发 并发 = 切换任务+保存状态。python中的生成器就具备这样一个特点,每次调用next都会回到生成器函数中执行代码,并且是基于上一次运行的结果,这就意味着生成器会自动切换任务并保存执行状态 def task1(): while True: yield print('task1 run') def task2(): g = task1() while True: next(g) print('task2 run') task2() 并发虽然实现了,但是效率如何呢? # 两个计算任务:一个采用生成器切换并发执行,一个直接串行调用 import time def task1(): a = 0 for i in range(50000000):

协程

有些话、适合烂在心里 提交于 2020-01-04 05:07:42
引子 上一节中我们知道GIL锁将导致CPython无法利用多核CPU的优势,只能使用单核并发的执行。很明显效率不高,那有什么办法能够提高效率呢? 效率要高只有一个方法就是让这个当前线程尽可能多的占用CPU时间,如何做到? 任务类型可以分为两种 IO密集型 和 计算密集型 对于计算密集型任务而言 ,无需任何操作就能一直占用CPU直到超时为止,没有任何办法能够提高计算密集任务的效率,除非把GIL锁拿掉,让多核CPU并行执行。 对于IO密集型任务任务,一旦线程遇到了IO操作CPU就会立马切换到其他线程,而至于切换到哪个线程,应用程序是无法控制的,这样就导致了效率降低。 如何能提升效率呢?想一想如果可以监测到线程的IO操作时,应用程序自发的切换到其他的计算任务,是不是就可以留住CPU?的确如此 一、单线程实现并发 单线程实现并发这句话乍一听好像在瞎说 首先需要明确并发的定义 并发:指的是多个任务同时发生,看起来好像是同时都在进行 , 实际上是切换 + 记录状态 并行:指的是多个任务真正的同时进行 早期的计算机只有一个CPU,既然CPU可以切换线程来实现并发,那么为何不能在线程中切换任务来并发呢? 上面的引子中提到,如果一个线程能够检测IO操作并且将其设置为非阻塞,并自动切换到其他任务 , 就这样可以提高CPU的利用率,指的就是在单线程下实现并发。 如何能够实现并发呢 ? 并发 = 切换任务

进程线程协程的区别

断了今生、忘了曾经 提交于 2020-01-04 04:52:05
一、概念   1、进程 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。   2、线程 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。   3、协程 协程是一种用户态的轻量级线程, 协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。 二、区别:   1、进程多与线程比较 线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别: 1) 地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,它们共享进程的地址空间,而进程有自己独立的地址空间 2)

golang并发(1)介绍

做~自己de王妃 提交于 2020-01-04 04:46:52
概述 简而言之, 所谓并发编程是指在一台处理器上 “ 同时 ” 处理多个任务。 随着硬件的发展,并发程序变得越来越重要。 Web 服务器会一次处理成千上万的请求。平板电脑和手机 app 在渲染用户画面同时还会后台执行各种计算任务和网络请求。即使是传统的批处理问题 -- 读取数据,计算,写输出 -- 现在也会用并发来隐藏掉 I/O 的操作延迟以充分利用现代计算机设备的多个核心。计算机的性能每年都在以非线性的速度增长。 宏观的并发是 指在一段时间内 , 有多个程序在同时运行 。 并发在微观上,是指在同一时刻只能有一条指令执行,但多个程序指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个程序快速交替的执行。 并行和并发 并行 (parallel) : 指在同一时刻,有多条指令在 多个处理器 上同时执行。 并发 (concurrency) : 指在同一时刻只能有一条指令执行 , 但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段, 通过 cpu 时间片轮转 使多个进程快速交替的执行。 大师曾以咖啡机的例子来解释并行和并发的区别。 并行 是两个队列 同时 使用 两台 咖啡机 (真正的多任务) 并发 是两个队列 交替 使用 一台 咖啡机 ( 假 的多任务)

Python进程、线程、协程之间的关系

微笑、不失礼 提交于 2020-01-04 04:45:31
一、从操作系统角度 操作系统处理任务, 调度单位是 进程 和 线程 。 1.进程: 表示一个程序的执行活动 (打开程序、读写程序数据、关闭程序) 2.线程: 执行某个程序时, 该进程调度的最小执行单位 (执行功能1,执行功能2) 一个程序至少有一个进程 一个进程至少有一个线程 1.并行: 需要处理的任务数 == CPU核心数量 两个任务 两个核心 任务1:------------- 任务2:------------- 2.并发: 需要处理的任务数 > CPU核心数量 三个任务 一个核心 任务1: ----- ------ 任务2: ------ 任务3: ------ 二、从程序角度 多进程和多线程 表示:当前程序可以同时执行多个任务 进程和线程都是由 操作系统调度完成 1.进程:    每个进程都是有自己独立的内存空间,不同进程之间的内存空间是不能共享。 不同进程之间的通信是由操作系统来完成的。 不同进程之间的通信效率低切换开销也大。 2.线程:   一个进程下可以有多个线程,同一个进程内的线程可以共享内存空间. 不同线程之间的通信 有进程 管理。 不同线程之间的通信效率高,切换开销小。 3.互斥锁:   共享意味着多个线程的竞争 会导致不安全问题。 为了保护内存空间的数据不被多个线程同时读写, 导致数据隐患, 于是诞生了" 互斥锁 "。 "互斥锁":

进程,线程和协程 并行与并发

喜欢而已 提交于 2020-01-04 04:45:13
一、进程 进程的出现是为了更好的利用CPU资源使到并发成为可能。 假设有两个任务A和B,当A遇到IO操作,CPU默默的等待任务A读取完操作再去执行任务B,这样无疑是对CPU资源的极大的浪费。聪明的老大们就在想若在任务A读取数据时,让任务B执行,当任务A读取完数据后,再切换到任务A执行。注意关键字切换,自然是切换,那么这就涉及到了状态的保存,状态的恢复,加上任务A与任务B所需要的系统资源(内存,硬盘,键盘等等)是不一样的。自然而然的就需要有一个东西去记录任务A和任务B分别需要什么资源,怎样去识别任务A和任务B等等。登登登,进程就被发明出来了。通过进程来分配系统资源,标识任务。如何分配CPU去执行进程称之为调度,进程状态的记录,恢复,切换称之为上下文切换。进程是系统资源分配的最小单位,进程占用的资源有: 地址空间 全局变量 文件描述符 各种硬件资源 相比线程和协程,进程是比较重量级的,它需要的资源很多。进程之间不共享内存变量,所以进程间的通信方式也多种多样: TCP REDIS等数据库 管道,文件等 二、线程 线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使得进程内并发成为可能。假设,一个文本程序,需要接受键盘输入,将内容显示在屏幕上,还需要保存信息到硬盘中。若只有一个进程,势必造成同一时间只能干一样事的尴尬(当保存时,就不能通过键盘输入内容

Python多进程、多线程、协程

醉酒当歌 提交于 2020-01-04 04:45:04
转载:https://www.cnblogs.com/huangguifeng/p/7632799.html 首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务。 一个CPU,在一个时间切片里只能运行一个程序。 从操作系统的角度: 进程和线程,都是一种CPU的执行单元。 进程:表示一个程序的上下文执行活动(打开、执行、保存...) 线程:进程执行程序时候的最小调度单位(执行a,执行b...) 一个程序至少有一个进程,一个进程至少有一个线程。 并行 和 并发: 并行:多个CPU核心,不同的程序就分配给不同的CPU来运行。可以让多个程序同时执行。 cpu1 ------------- cpu2 ------------- cpu3 ------------- cpu4 ------------- 并发:单个CPU核心,在一个时间切片里一次只能运行一个程序,如果需要运行多个程序,则串行执行。 cpu1  ----  ---- cpu1    ----  ---- 多进程/多线程: 表示可以同时执行多个任务,进程和线程的调度是由操作系统自动完成。 进程:每个进程都有自己独立的内存空间,不同进程之间的内存空间不共享。 进程之间的通信有操作系统传递,导致通讯效率低,切换开销大。 线程:一个进程可以有多个线程

3.4.1 Greenlet

那年仲夏 提交于 2020-01-02 17:11:29
协程 协程,又称微线程,纤程。英文名coroutine。简单说:协程是一种用户态的轻量级线程。 协程拥有自己的寄存器上下文和栈。写成调度切换时,将寄存器上下文和栈保存到其他地方,在且回来的时候,恢复先前保存的寄存器上下文和栈。 因此,协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换句话说:进入上一次离开时所处逻辑流的位置。 协程的优点: 无需线程上下文切换的开销 无需原子操作锁定及同步的开销 #改一个变量就是原子操作 方便切换控制流,简化编程模型 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。 缺点: 无法利用多核资源:协程的本质是个单线程,它不能同时将单个CPU的多个核用上,协程需要和进程配合才能运行在多核CPU上,当然我们日常所编写的绝大部分应用都没有这个必要,除非是CPU密集型应用。 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序 下面是一个使用yield实现协程的示例 import time, queue def consumer(name): #函数中使用yield语句,函数会变成一个生成器 print('Starting to sell iphone...') #2.1输出 3.1输出 while True: new_iphone = yield #2