zoukankan      html  css  js  c++  java
  • 协程与多线程的区别

    转载:

    ----------------------------------------------------------------------第一篇-------------------------------------------------------------------

           coroutine和真正的thread的区别挺多,但是也不好说是限制,须知Contiki的使用环境
    是传感器网络节点,一般来说,大都是内存极其受限,相比之下,CPU资源是可以不那么
    受限的(或者这么说,CPU工作时间长些仅仅是影响节点的寿命,而RAM不够用则节点根本
    不可能工作起来)。

    protothread就是为了解决这个多线程会消耗过多的RAM的问题而用增加CPU处理工作来做交换。

    每个函数(protothread)在yield的时候都完全返回,也就是相当于多个“线程”共用同一个
    堆栈。但是这和event-based的系统(比如tinyos)的区别在于,这个系统编程的时候你还是
    可以认为是顺序执行的(yield之后如果继续执行的话,不是从函数开头而是从上次yield的
    地方继续执行),event-based的系统则必须人为将系统拆分成许多event(简单的理解,你可
    以认为就是把程序全写成状态机的形式,很多情况来说,这对人来说不是一个很好驾驭的
    模型,比如我们会很习惯做了这个时候干什么,条件没成熟就继续做什么;可是要弄成状
    态机形式,你就必须自己分成几个状态,弄出状态转移图,而用这种类似thread的protothread
    则不需要显式地体现出来你的状态机)。

    至于protothread(coroutine和它本质一样)的限制,取决于实现,如果使用可移植的switch来实现,
    那么限制超多,不能用switch了;如果使用GNU的computed goto来实现,则没有这个限制;
    但是不管是什么实现,都需要注意,如果你希望函数的auto变量保存上次的值的话,必须声明成
    static,这才是这类在C语言中实现coroutine类机制的本质限制。

    这些东西,说到最后就是一个continuation的概念,只不过在函数式编程社区以外都不怎么用这个
    概念而已。

    上面关于protothread的说得可能过于泛泛,如果想知道详情,还是应该读这篇论文:
    Protothreads: Simplifying Event-Driven Programming of Memory-Constrained Embedded Systems
    Adam Dunkels, Oliver Schmidt, Thiemo Voigt, Muneeb Ali

    Protothread或者叫Coroutine,主要就是提供continuation point。即函数从yield返回后,下次调用会接着yeild的下一句执行。目的之一是简化代码结构,增强可读性。当然,Iterator这样的东西也可以比较方便的实现。

    coroutine可以是有自己独立堆栈的(Thread的协调多任务用法),也可以是共享堆栈的。共享堆栈就是如freertos/coroutine,protothread这样的实现。好处是节约内存;最大劣势是共享堆栈,因此所有栈自动变量在yield会丢失。
    解决办法要么是用static/全局变量,不在栈上保存,但是可能丢失重入特性(是否丢看实现手段);要么用malloc之类的使用堆,但存在内存泄漏(典型为Yield之后Reset),内存碎片的问题(malloc自身,决定于其算法)。

    实现手段上,符合标准,可移植的,是基于switch的实现。为了使coroutine可用并且好用,至少仰赖于以下C标准的规定,或者C标准中没有说,但是经讨论,是合法描述的情形:
    - 宏展开后,宏中的代码都在一个物理行上。
    - switch的case可以和for/if之类的语句嵌套。即switch(bbb) { for(xx; xx; xx) { case 1: ... ; case 2: yyy} }是合法的。
    第二条是switch实现的核心,如果有变化,就over。

    标准switch实现的坏处:
    - switch必须谨慎使用:嵌入的switch中间不能带yield,(return,exit看实现)之类的返回点。这个可以用if/else避免。
    - switch靠后的continuation point的调用一次额外开销比较大,要一个一个比较过去。

    使用嵌入汇编,GNU的label,computed goto等实现,限制要少,效率也高。问题一个是可移植;另外一个是编译器优化是否导致问题,嵌入式汇编这个很明显,GNU的我没用过,没体会。

    ----------------------------------------------------------------------第一篇-------------------------------------------------------------------

  • 相关阅读:
    使用nodejs消费SAP Cloud for Customer上的Web service
    如何在SAP Cloud for Customer自定义BO中创建访问控制
    SAP云平台运行环境Cloud Foundry和Neo的区别
    SAP成都研究院马洪波:提升学习力,增强竞争力,收获一生乐趣
    SAP Netweaver的负载均衡消息服务器 vs CloudFoundry的App Router
    写在Github被微软收购之际
    在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务
    Java实现 LeetCode 517 超级洗衣机
    Java实现 LeetCode 517 超级洗衣机
    Java实现 LeetCode 517 超级洗衣机
  • 原文地址:https://www.cnblogs.com/yyx1-1/p/6290582.html
Copyright © 2011-2022 走看看