当前位置: 首页 > news >正文

【node学习】协程

协程

要理解generator就必须知道一个概念,那就是协程

1. 基本概念

协程,又成为微线程(coroutine)。

进程(process) vs 线程(thread)

我们都知道在操作系统级别上有两个重要的概念(也是实体):进程(process)和线程(thread),这两个东西是用于操作系统模拟并行的,在单个CPU上,os通过调度算法,让CPU轮流执行线程或者进程,来达到程序的并发执行。

那么协程又是什么?首先要明确的是,协程是编译器级别的,而并非线程和进程一样是操作系统级别的。协程的实现,通过是对某个语言做相应的提议,然后通过后成编译器标准,然后编译厂商来实现该机制。

2. 作用

协程的作用是什么?

简单来说,就是实现函数的分段式执行。就是一个函数的执行可以主动放弃CPU的控制权,先挂起,让其他的函数先执行,然后在返回,从上次执行结束的地方继续执行。

这样看起来很像是多线程轮流执行。但是却有着很大的区别:协程是一个线程执行

  • 因为是一个线程执行,所以不存在线程的切换,而是由程序自身控制,也就不存在所谓的线程切换的开销。

  • 不需要多线程的锁机制。因为只有一个线程,也就不存在同时写变量的冲突。在协程中控制共享资源不加锁,只需要判断状态就好了。这也说明协程的执行效率很高一些。

举个生产者消费者模型基于抢占式多线程编程的实现(伪代码)

// 资源,队列容器
var q = [];

// 消费者进程
loop(); // 循环等待
lock(q); // 加锁
var item = getResourceFrom(q); // 获取资源
unlock(q); // 操作结束,资源解锁
operatingResource(item);
sleep;

// 生成者线程
loop(); // 循环等待
var item = createResource(p); // 生产资源
lock(q); // 加锁
q.push(item); // 写入资源
unlock(q); // 解锁

可以看到,以上的代码中有两个特点

  1. 对资源操作需要进行加锁和解锁的操作。(保证线程安全)

  2. 消费者线程必须通过sleep,让出CPU,用于执行生产者线程使用。

那么如果是协程的编程模式,就简单地多。

var q = [];
var count = 0;

// 消费者
function *consumer() {
    while (true){
       var item = yield producer();
       console.log(item); 
    }
}

// 生产者
function producer() {
    q.push(count++);
}

function main () {
    const consumerGen = consumer();
    // 我们可以通过代码来控制其交替执行

    // 执行到获取item之前,放弃执行权,先执行producer(),
    consumerGen.next();
    // 之后可以获取item,然后再放弃执行权,执行producer,一直循环
    consumerGen.next(q.shift()); // 0
    consumerGen.next(q.shift()); // 1
    consumerGen.next(q.shift()); // 2
    consumerGen.next(q.shift()); // 3
    consumerGen.next(q.shift()); // 4
    consumerGen.next(q.shift()); // 5
}

main();

最后说几句

好久在这上面写博客了,最近一直忙于毕业设计和学习node。

参考

  1. 协程-廖雪峰

  2. C++ 协程与网络编程

  3. 谈谈协程和C语言的协程

  4. 协程(Coroutine)并不是真正的多线程

  5. 协程(一)原理

相关文章:

  • 【转】JVM 分代GC策略分析
  • centos下编译安装MySQL5.7.16
  • Meta标签
  • OpenCV例程实现人脸检测
  • bt和wifi的共存
  • 使用Powershell链接到Office 365
  • Bootstrap-datepicker设置开始时间结束时间范围
  • django中的filter详解
  • CDN学习笔记二(技术详解)
  • macOS 中的 Rootless 机制
  • python环境搭建-设置PyCharm软件的配色方案和Python解释器
  • mod_fastcgi和mod_fcgid的区别
  • [摘录]第六章 用负激励促进新陈代谢
  • 4. 路由到控制器 - Laravel从零开始教程
  • 给MVC来一个谬论
  • Android开源项目规范总结
  • C++类中的特殊成员函数
  • Fastjson的基本使用方法大全
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • java中的hashCode
  • mockjs让前端开发独立于后端
  • Sass 快速入门教程
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • webpack+react项目初体验——记录我的webpack环境配置
  • Xmanager 远程桌面 CentOS 7
  • 阿里云购买磁盘后挂载
  • - 概述 - 《设计模式(极简c++版)》
  • 高程读书笔记 第六章 面向对象程序设计
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 用mpvue开发微信小程序
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • #pragma预处理命令
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (02)vite环境变量配置
  • (9)YOLO-Pose:使用对象关键点相似性损失增强多人姿态估计的增强版YOLO
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)Oracle存储过程编写经验和优化措施
  • (转)shell调试方法
  • .jks文件(JAVA KeyStore)
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .NET 动态调用WebService + WSE + UsernameToken
  • .net 获取url的方法
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .Net组件程序设计之线程、并发管理(一)
  • .py文件应该怎样打开?
  • /var/lib/dpkg/lock 锁定问题
  • @Data注解的作用
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择