协程

Unity C#笔记 协程详解(转)

ε祈祈猫儿з 提交于 2020-03-08 13:00:47
目录 什么是协程 多线程 协程 协程的使用场景 协程使用示例 Invoke的缺陷 协程语法 开启协程 终止协程 挂起 协程的执行原理 什么是协程 在Unity中,协程(Coroutines)的形式是我最喜欢的功能之一,我都会使用它来控制需要定时的。 协同程序,在主程序运行的同时,开启另外一段逻辑处理,来协同当前程序的执行。 可能看了这段文字介绍还是有点模糊,其实可以用多线程来比较。 多线程 多线程,顾名思义,多条同时执行的线程。 最初,多线程的诞生是为了解决IO阻塞问题,如今多线程可以解决许多同样需要异步方法的问题(例如网络等)。 所谓异步,通俗点讲,就是我走我的线程,你走你的线程。当某个线程阻塞时,另一个线程不会受影响继续执行。 需要认识到的是,多线程并不是真正意义上的多条线程同时执行。 它的实际是将一个时间段分成若干个时间片,每个线程轮流运行一个时间片。 (如图,将执行步骤切分成极小的粒度,然后依次运行) 但是由于时间片粒度非常非常小,几乎看不出区别,所以程序执行效果跟真正意义上的并行执行效果基本一致。 多线程的缺陷 然而多线程有一个坏处,就是可能造成共享数据的冲突。 假如有一个变量i = 0, Step1_1的操作是进行++i操作,Step2_1的操作是进行--i操作。 我们预期最终结果i为0。 但由于操作切分得过小,可能会发生这样顺序的事: 线程1:访问i, 将0存到寄存器

协程—概念以及基本使用

爷,独闯天下 提交于 2020-03-07 11:13:41
协程简述 是操作系统不可见的。 协程本质就是一条线程,多个任务在一条线程上来回切换。 利用协程这个概念实现的内容:来规避IO操作,就达到了我们将一条线程中的io操作降到最低的目的。 切换 并 规避io 的两个模块 一、gevent: 利用了 greenlet 底层模块完成的切换 + 自动规避io的功能 二、asyncio:利用了 yield 底层语法完成的切换 + 自动规避io的功能(tornado异步框架的底层就是yield) yield from:更好的实现协程 send:更好的实现协程 asyncio模块:基于python原生的协程的概念正式的被成立。 特殊的在python中提供协程功能的关键字:aysnc await 来源: https://www.cnblogs.com/liuhaidon/p/12433077.html

Python-线程池、进程池,协程

大憨熊 提交于 2020-03-06 20:48:37
线程池&进程池 在python2中没有提供,在python3之后才提供 作用:保证程序中最多可以创建的线程的个数 import time from concurrent.futures import ThreadPoolExecutordef task(n1,n2): time.sleep(1) print('星空不问赶路人')pool = ThreadPoolExecutor(10) # 创建线程池for i in range(100): pool.submit(task,i,1)pool.shutdown(True) # 等线程池中任务执行完毕之后,再继续往后走print('岁月不负有心人') import time from concurrent.futures import ThreadPoolExecutordef task(arg): time.sleep(1) print('星空不问赶路人') return '岁月不负有心人'ret = pool.map(task,range(1,20)) # 具有返回值print('end',ret)pool.shutdwon(True)for i in ret: print(i) # 直接输出i import timefrom concurrent.futures import ThreadPoolExecutordef task

Python--线程队列(queue)、multiprocessing模块(进程对列Queue、管道(pipe)、进程池)、协程

那年仲夏 提交于 2020-03-05 00:36:02
队列(queue) 队列只在多线程里有意义,是一种线程安全的数据结构。 get与put方法 ''' 创建一个“队列”对象 import queue q = queue.Queue(maxsize = 10) queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。 将一个值放入队列中: q.put() 调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为True。如果队列当前为空且block为True,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为False,put方法将引发Full异常。 import queue q=queue.Queue(3) q.put(11) q.put(22) q.put(33) q.put(44,False) #queue.Full ==q.put_nowait() 将一个值从队列中取出 q.get() 调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False

go 语言并行

被刻印的时光 ゝ 提交于 2020-03-04 10:31:52
使用 go func_name() 算是并发,而不是并行。 还需要 import ( "runtime" ) runtime.GOMAXPROCS(x) 这两部来设置并行的协程数x,go 1.5版本后这个协程数默认是计算机核数,但是最好还是手动设置一下。然后就能并行了。 来源: https://www.cnblogs.com/zealousness/p/12407849.html

Goroutine泄漏

你。 提交于 2020-03-03 15:55:13
概述 在Go中,goroutine很轻量级,随便创建成千上万个goroutine不是问题,但要注意,要是这么多的goroutine一致递增,而不退出,不释放资源,可就麻烦了。 本文介绍goroutine泄露的实际场景,并讨论如何解决该问题。 产生原因分析 产生goroutine leak(协程泄露)的原因可能有以下几种: goroutine由于channel的读/写端退出而一直阻塞,导致goroutine一直占用资源,而无法退出 goroutine进入死循环中,导致资源一直无法释放 goroutine终止的场景 一个goroutine终止有以下几种情况: 当一个goroutine完成它的工作 由于发生了没有处理的错误 有其他的协程告诉它终止 实际的goroutine leak 生产者消费者场景 func main ( ) { newRandStream := func ( ) <- chan int { randStream := make ( chan int ) go func ( ) { defer fmt . Println ( "newRandStream closure exited." ) defer close ( randStream ) // 死循环:不断向channel中放数据,直到阻塞 for { randStream <- rand . Int ( ) }

Python学习第九天

拟墨画扇 提交于 2020-03-03 08:29:20
生产者-消费者模型: 看下面的例子哦: 1 import threading,queue 2 import time 3 def consumer(n): 4 while True: 5 print("\033[32;1mconsumer [%s]\033[0m get task: %s"%(n,q.get())) 6 time.sleep(1) 7 q.task_done() 8 def producer(n): 9 count=1 10 while True: 11 print('producer [%s] produced a new task: %s'%(n,count)) 12 q.put(count) 13 count += 1 14 q.join()#queue is emtpy 15 print('all tasks has been cosumed by consumers...') 16 q=queue.Queue() 17 c1=threading.Thread(target=consumer,args=[1,]) 18 c2=threading.Thread(target=consumer,args=[2,]) 19 c3=threading.Thread(target=consumer,args=[3,]) 20 21 p=threading.Thread

Python_协程

邮差的信 提交于 2020-03-02 22:26:31
引子   之前我们学习了线程、进程的概念,了解了在操作系统中 进程是资源分配的最小单位,线程是CPU调度的最小单位。 按道理来说我们已经算是把cpu的利用率提高很多了。但是我们知道无论是创建多进程还是创建多线程来解决问题,都要消耗一定的时间来创建进程、创建线程、以及管理他们之间的切换。   随着我们对于效率的追求不断提高, 基于单线程来实现并发 又成为一个新的课题,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发。这样就可以节省创建线进程所消耗的时间。   为此我们需要先回顾下并发的本质:切换+保存状态   cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作系统强制控制),一种情况是该任务发生了阻塞,另外一种情况是该任务计算的时间过长       ps:在介绍进程理论时,提及进程的三种执行状态,而线程才是执行单位,所以也可以将上图理解为线程的三种状态    一:其中第二种情况并不能提升效率,只是为了让cpu能够雨露均沾,实现看起来所有任务都被“同时”执行的效果,如果多个任务都是纯计算的,这种切换反而会降低效率。   为此我们可以基于yield来验证。yield本身就是一种在单线程下可以保存任务运行状态的方法,我们来简单复习一下: #1 yiled可以保存状态,yield的状态保存与操作系统的保存线程状态很像,但是yield是代码级别控制的,更轻量级

Python--Demo18--异步IO之协程

≯℡__Kan透↙ 提交于 2020-03-02 12:50:04
协程: 使用一个线程来实现异步操作的。它相对于多线程执行效率高,不存在线程切换;此外协程不牵扯多线程中锁的机制,所以不必考虑加锁这些复杂操作。 协程是通过generator来实现的,就是yield关键字和send()函数的使用。 生成器的yield关键字: yield关键字可以将值(信息)返回,同时在信息返回后使程序停留在当前行。 >>> def test(): ... number=1 ... while True: ... number*=2 ... yield number ... print('yield下面的代码') ... >>> t=test() >>> t <generator object test at 0x000001E372BDA5F0> >>> type(t) <class 'generator'> >>> next(t) 2 >>> >>> next(t) yield下面的代码 4 >>> next(t) yield下面的代码 8 >>> next(t) yield下面的代码 16 生成器的send()函数: yield还可以接收调用者传递过来的信息:通过sned()函数,将值(消息)传递给生成器。生成器通过yield前面的变量来接收传递过来的值。 >>> def tst(): ... number=1 ... while True: ... pam

Python - 协程

本小妞迷上赌 提交于 2020-03-02 12:07:50
一、简介 协程是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是协程: 协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。 需要强调的是: # 1.python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cup执行权限,切换其它线程运行) # 2.单线程内开户协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(非io操作的切换与效率无关) 对比操作系统控制线程的切换,用户在单线程内控制协程的切换 优点如下: # 1.协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级 # 2.单线程内就可以实现并发的效果,最大限度地利用cpu 缺点如下: # 1.协程的本质是单线程,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程 # 2.协程指的是单线程,因而一旦协程出现阻塞,将会阻塞整个线程 总结协程特点: 1. 必须在只有一个单线程里实现并发 2. 修改共享数据不需要加锁 3. 用户程序里自己保存多个控制流的上下文栈 附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield,greenlet都无法实现,就用到了gevent模块(select机制)) 二、Greenlet 如果我们在单个线程内有20个任务