协程

【深入Lua】理解Lua中最强大的特性-coroutine(协程)

孤街浪徒 提交于 2020-04-07 11:29:42
点击进入我的新博客 ###coroutine基础 Lua所支持的协程全称被称作协同式多线程(collaborative multithreading)。Lua为每个coroutine提供一个独立的运行线路。然而和多线程不同的地方就是,coroutine只有在显式调用yield函数后才被挂起,同一时间内只有一个协程正在运行。 Lua将它的协程函数都放进了coroutine这个表里,其中主要的函数如下 摘取一段 云风 的代码来详尽解释协程的工作机制,在这段代码中,展示了main thread和协程co之间的交互: <!-- lang: lua --> function foo(a) print("foo", a) return coroutine.yield(2 * a) end co = coroutine.create(function ( a, b ) print("co-body", a, b) local r = foo(a + 1) print("co-body", r) local r, s = coroutine.yield(a + b, a - b) print("co-body", r, s) return b, "end" end) print("main", coroutine.resume(co, 1, 10)) print("main", coroutine

python的多线程、多进程、协程用代码详解

醉酒当歌 提交于 2020-04-06 16:39:40
前言 文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。 作者:刘早起早起 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http://t.cn/A6Zvjdun 很多时候我们写了一个爬虫,实现了需求后会发现了很多值得改进的地方,其中很重要的一点就是爬取速度。本文就通过代码讲解如何使用 多进程、多线程、协程 来提升爬取速度。注意:我们不深入介绍理论和原理,一切都在代码中。 同步 首先我们写一个简化的爬虫,对各个功能细分,有意识进行函数式编程。下面代码的目的是访问300次百度页面并返回状态码,其中parse_1函数可以设定循环次数,每次循环将当前循环数(从0开始)和url传入parse_2函数。 性能的消耗主要在IO请求中,当单进程单线程模式下请求URL时必然会引起等待 示例代码就是典型的串行逻辑,parse_1将url和循环数传递给parse_2,parse_2请求并返回状态码后parse_1继续迭代一次,重复之前步骤 多线程 因为CPU在执行程序时每个时间刻度上只会存在一个线程,因此多线程实际上提高了进程的使用率从而提高了CPU的使用率 实现多线程的库有很多,这里用concurrent.futures中的ThreadPoolExecutor来演示

线程queue、线程进程池,协程

故事扮演 提交于 2020-04-06 11:32:55
线程queue import queue q = queue.Queue() #先进先出 q = queue.LifoQueue() #先进后出 t = queue.PriorityQueue() #优先级取数据,通常这个元组的第一个值是int类型 q.put('123') q.put('qweqwe') print(q.get()) print(q.get()) t.put('100', 'tank') t.put('10', 'nick') t.put('1', 'jason') print(t.get()) print(t.get()) print(t.get()) q.task_done() q.task_done() q.join() 线程定时器 from threading import Thread, Timer import time def task(): print('线程执行了') time.sleep(2) print('线程结束了') t = Timer(3, task) #过了3秒后开启了一个线程 t.start() 多线程实现socket服务端 #服务端 from threading import Thread import socket def talk(conn): while True: try: info = conn.recv(1024)

进程,线程和协程

强颜欢笑 提交于 2020-04-06 10:50:27
1,任务调度 要理解进程和线程,必须要先了解一下操作系统的一些相关概念。大部分操作系统(如Windows、Linux)的 任务调度 是采用 时间片轮转的抢占式调度方式 ,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行。任务执行的一小段时间叫做时间片,任务正在执行时的状态叫运行状态,任务执行一段时间后强制暂停去执行下一个任务,被暂停的任务就处于就绪状态等待下一个属于它的时间片的到来。这样每个任务都能得到执行,由于CPU的执行效率非常高,时间片非常短,在各个任务之间快速地切换,给人的感觉就是多个任务在“同时进行”,这也就是我们所说的并发(别觉得并发有多高深,它的实现很复杂,但它的概念很简单,就是一句话:多个任务同时执行)。多任务运行过程的示意图如下: 操作系统中的任务调度 2,进程 我们都知道计算机的核心是CPU,它承担了所有的计算任务;而操作系统是计算机的管理者,它负责任务的调度、资源的分配和管理,统领整个计算机硬件;应用程序侧是具有某种功能的程序,程序是运行于操作系统之上的。 进程 是一个具有一定独立功能的 程序在一个数据集上的一次动态执行的过程, 是应用程序运行的载体, 操作系统会以进程为单位,分配系统资源(CPU时间片、内存等资源),进程是资源分配的最小单位 。 进程一般由程序、数据集合和进程控制块三部分组成。 程序用于描述进程要完成的功能

你知道GO语言的关键特性吗?

久未见 提交于 2020-04-01 13:56:07
小编今天就给大家讲一下go语言的关键特性,GO语言之所以厉害,是因为它在服务端的开发中,总能抓住程序员的痛点,以最直接、简单、高效、稳定的方式来解决问题。这里我们并不会深入讨论GO语言的具体语法,只会将语言中关键的、对简化编程具有重要意义的方面介绍给大家,跟随大师们的脚步,体验GO的设计哲学。想要 学习go语言 和 go语言入门 的小伙伴就要好好看看了。 GO语言的关键特性主要包括以下几方面: 并发与协程 基于消息传递的通信方式 丰富实用的内置数据类型 函数多返回值 defer机制 反射(reflect) 高性能HTTP Server 工程管理 编程规范 在当今这个多核时代,并发编程的意义不言而喻。当然,很多语言都支持多线程、多进程编程,但遗憾的是,实现和控制起来并不是那么令人感觉轻松和愉悦。Golang不同的是,语言级别支持协程(goroutine)并发(协程又称微线程,比线程更轻量、开销更小,性能更高),操作起来非常简单,语言级别提供关键字(go)用于启动协程,并且在同一台机器上可以启动成千上万个协程。 对比JAVA的多线程和GO的协程实现,明显更直接、简单。这就是GO的魅力所在,以简单、高效的方式解决问题,关键字go,或许就是GO语言最重要的标志。 基于消息传递的通信方式 在异步的并发编程过程中,只能方便、快速的启动协程还不够。协程之间的消息通信,也是非常重要的一环,否则

异步爬虫

我与影子孤独终老i 提交于 2020-03-25 20:33:50
<!doctype html> 异步爬虫 异步爬虫 基于线程池 搭建模拟网站,基于Flask框架 templates设置如下图,Flask框架只能使用jinja2进行渲染 第二步: 在templates中创建test.html 下面是python搭建Flask框架 #!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask,render_template from time import sleep 实例化一个app app = Flask(name) 创建视图函数&路由地址 @app.route('/bobo') def index_1(): sleep(2) return render_template('test.html') @app.route('/jay') def index_2(): sleep(2) return render_template('test.html') @app.route('/tom') def index_3(): sleep(2) return render_template('test.html') if name == "main": #debug=True表示开启调试模式:服务器端代码被修改后按下保存键会自动重启服务 app.run(debug=True)

Java 中的协程库 - Quasar

早过忘川 提交于 2020-03-25 18:33:14
一、协程 一个进程可以产生许多线程,每个线程有自己的上下文,当我们在使用多线程的时候,如果存在长时间的 I/O 操作,线程会一直处于阻塞状态,这个时候会存在很多线程处于空闲状态,会造成线程资源的浪费。这就是协程适用的场景。 协程,其实就是在 一个线程 中,有一个总调度器,对于多个任务,同时只有一个任务在执行,但是一旦该任务进入阻塞状态,就将该任务设置为挂起,运行其他任务,在运行完或者挂起其他任务的时候,再检查待运行或者挂起的任务的状态,使其继续执行。 协程的方式更多用来做阻塞密集型(比如 I/O)的操作,计算密集型的还是使用线程更加合理。 Java 官方并没有协程库。但是伟大的社区提供了一个优秀的库,它就是 Quasar。 二、Quasar 简介 Quasar 提供了高性能轻量级的线程,提供了类似 Go 的 channel,Erlang 的 actor,以及其它的异步编程的工具,可以用在 Java 和 Kotlin 编程语言中。 Quasar 最主要的贡献就是提供了轻量级线程的实现 —— fiber。Fiber 的功能和使用类似 Thread, API 接口也类似,所以使用起来没有违和感,但是它们不是被操作系统管理的,它们是由一个或者多个 ForkJoinPool 调度。一个空闲的 fiber 只占用 400 字节内存,切换的时候占用更少的 CPU,你的应用中可以有上百万的

Python 中的协程 (3) 基础概念

戏子无情 提交于 2020-03-25 15:36:58
1 进程和线程 进程 Process:一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式)。 线程 Thread: 线程是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。线程的本质:线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。 进程和线程的区别:进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些

python 协程

删除回忆录丶 提交于 2020-03-23 19:13:29
协程之前我们明白Python的进程和线程,这里我们来说一下协程 子程序切换不是线程切换,而是由程序自身控制 没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁 协程实现 def custumer(): r = '' while True: n = yield r # 接受send的值 返出yield的值 if not n: return print('custer {}'.format(n)) r = 'done' def produce(c): c.send(None) # 启动 n = 0 while n < 5: n += 1 print('custer {}'.format(n)) r = c.send(n) print('custer return {}'.format(r)) c.close() c = custumer() produce(c) 本文首发于 python黑洞网 ,博客园同步更新 来源: https://www.cnblogs.com/pythonzhilian/p/12553890.html

协程 和 async await

拥有回忆 提交于 2020-03-23 15:50:59
协程, 是 为了 避免 闭包传递变量 的 性能损耗 而产生 。 如果不是 为了 避免 闭包传递变量 的 性能损耗 , 线程池 和 Task 已经够了, 不需要 再设计 出 协程 来 。 闭包, 会 让 所有共享 的 变量 变成 引用 访问 的 方式,包括 值变量 。 因为 闭包 是将 变量 放到 堆 里 共享 。 协程 就是在 堆 里 模拟出一个 堆栈 和 协程“上下文” 存储区, 这和 操作系统 的 线程 堆栈 和 上下文 架构 是 相似 的 。 上下文存储区 保存 每个 协程 的 堆栈 的 栈顶 栈底, 在 切换 协程 时, 将 栈顶 栈底 存入 CPU 寄存器, 这样, 代码 中 对 变量 的 访问 就可以 和 线程 一样, 通过 编译在 指令中 的 偏移量 操作数 加上 栈底 的 地址 就可以得到 变量 的 地址 。 这样 对 函数 局部变量 的 访问 就和 线程 一样 , 指令 偏移量 操作数 + 栈底 , 这样 一次 寻址 。 避免了 闭包 将 变量 变成 引用访问 的 二次寻址 带来 的 性能损耗 。 所以, C# 的 async await 本身 就 包含了 一个 协程 的 实现, 这大概也是 C# async await 要通过 编译器 把 代码 编译为 状态机 而不是 Task.ContinueWith() 的 原因 。 协程 需要 编译器 在 汇编 层面 实现