当前位置: 首页 > 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来一个谬论
  • 2017前端实习生面试总结
  • AHK 中 = 和 == 等比较运算符的用法
  • css选择器
  • ES6 学习笔记(一)let,const和解构赋值
  • express + mock 让前后台并行开发
  • Java教程_软件开发基础
  • Linux gpio口使用方法
  • Node + FFmpeg 实现Canvas动画导出视频
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • Phpstorm怎样批量删除空行?
  • Sass Day-01
  • Spring Boot快速入门(一):Hello Spring Boot
  • vue学习系列(二)vue-cli
  • Webpack 4 学习01(基础配置)
  • 大主子表关联的性能优化方法
  • 关于springcloud Gateway中的限流
  • 聚类分析——Kmeans
  • 容器服务kubernetes弹性伸缩高级用法
  • 小试R空间处理新库sf
  • 正则与JS中的正则
  • ​第20课 在Android Native开发中加入新的C++类
  • ​力扣解法汇总946-验证栈序列
  • #AngularJS#$sce.trustAsResourceUrl
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • $jQuery 重写Alert样式方法
  • (1)常见O(n^2)排序算法解析
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (c语言)strcpy函数用法
  • (SpringBoot)第七章:SpringBoot日志文件
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (转)程序员技术练级攻略
  • . Flume面试题
  • .NET Core 通过 Ef Core 操作 Mysql
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .net Signalr 使用笔记
  • .net 微服务 服务保护 自动重试 Polly