zoukankan      html  css  js  c++  java
  • Actor 模型 / CSP模型 / 共享内存模型

     

    CSP模型 通信顺序进程,其实就是基于channel的消息通信,在ROS中,这种channel称作主题topic

    erlangactor的代表性语言,goCSP的代表性语言

     

    还有几个没怎么看的答案,不过都差不多了,这个讲历史比较多,也比较透彻,很有用,需要再仔细看!

    https://stackoverflow.com/questions/22621514/is-scalas-actors-similar-to-gos-coroutines/22622880?r=SearchResults#22622880

    https://stackoverflow.com/questions/20171442/is-communicating-sequential-processes-csp-an-alternative-to-the-actor-model-in?r=SearchResults

    http://en.wikipedia.org/wiki/Communicating_sequential_processes#Comparison_with_the_Actor_Model

    理解ACTOR和CSP模型,有python源码。

    https://www.codercto.com/a/9890.html

     

    Actor 模型与Object模型

    Theron框架是一个基于Actor模型的并发编程的C++库。而Actor模型使得Theron框架可以直接有效的创建并行分布式的应用。Theron框架提供了很多轻量便携的函数接口API,可以使用在LinuxWindowsMacARMMatlab环境。 

    我们知道面向对象编程中使用的是Object模型,宣扬一切皆是对象,数据+行为=对象。而Actor模型则认为一切皆是Actor,Actor模型内部的状态由自己的行为维护,外部线程不能直接调用对象的行为,必须通过消息才能激发行为,也就是使用消息传递机制来代替Object模型的成员方法的调用,这样就保证Actor内部数据只能被自己修改。Actor模型=数据+行为+消息。 

    但是C++是一种面向对象的语言,所以最终还是通过类来封装这种actor的机制,多线程的实现也是依靠内存共享的多线程机制设计的,只不过这些事情Theron源码已经帮我们完成了,我们直接使用它给出的类接口即可。Theron框架的多线程基础支持pthreads,Windows threads,boost::thread和C++11 threads四种传统类型来构建。多说一嘴,因为Theron框架在C++中说到底还是通过类封装实现Actor模型的,自然我们直接通过类对象调用类中方法数据。但是为了保证Theron框架生态的完整性,并且真正体现actor模型的优越性,我们还是不要如此为好。 

    基于Object模型与Actor模型区别如图3所示。

     

     

    这里写图片描述

    (a) 

     

    这里写图片描述

    (b) 

    图3 基于Object机制与基于Actor机制的比较 

    从图中可以看到,类A的对象成员方法调用类B的对象成员方法需要经过A::call调用B::called方法,然后等待B::called方法执行完成并且返回响应,最后A::call继续上次调用的地方后面执行下去。而在Actor模型中,Actor A先发送消息给Actor B,然后即刻就返回继续执行下面的程序,而Actor B中收到消息被唤醒和Actor A并行执行下去。 

    至此,Actor模型就可以看出这种消息机制的线程调用最大好处是非阻塞的,多个线程可以同时并发进行,无需等待被调用方法执行完成返回消息的响应。当然,看到此处大家或许跟我一样有一点困惑的地方,即万一我们后面的程序需要立即使用它返回的响应消息怎么办呢?其实这也算Actor存在的一点不足之处,需要我们在设计多线程前考虑你的程序到底适不适合这种机制,后面我们会再详细描述。 

    --------------------- 

    作者:无鞋童鞋 

    来源:CSDN 

    原文:https://blog.csdn.net/FX677588/article/details/74359823 

    版权声明:本文为博主原创文章,转载请附上博文链接!

     

    3.2 Actor模型与共享内存模型不同点 

    Actor这种独立并发的模型,与另一种共享内存模型完全相反。Actor之间通过消息传递方式进行合作,相互线程独立。随着多核时代和分布式系统的到来,共享内存模型其实不适合开发的。我们以酒店厨房做菜为例,如图4所示。

     

     

    这里写图片描述

    图4 Actor模型与共享内存模型的比喻图示

     

    ①、单线程编程,如图4(a)——犹如酒店只有一个厨师员工(一个线程),所有菜按点菜顺序与工序完成到底就行; 

    ②、共享内存的多线程编程,如图4(b)——犹如酒店厨房是由洗菜工,刀工,掌勺,服务员等(每个人是一个线程),他们之间的确能通过合作能比一个厨师完成所有工序要快。我们需要考虑的是菜相当于是他们共享的资源,每次只能一个人在对其做处理,虽然有多道菜品,但是总会在穿插间存在等待。 

    ③、Actor模型的多线程编程,如图4(c)——犹如酒店有多个厨师,分别是川菜师傅,鲁菜师傅,徽菜师傅等等,他们只要接到客人点菜的需求,整个人独自完成相对应菜系的工序,之间不管对方师傅要干嘛,如此多线程工作就大大增加了效率,并且不存在互相等待资源的情况,做好了自己发消息给服务员端菜即可。 

    这样我们就可以看出Actor模型异步消息传递来触发程序并行执行,虽然不如直接调用来的直接而方便,但是它可以让大量消息真正意义上同步执行。同时消息让Actor之间解耦,消息发出去之后执行成功与否,耗时多少等等只要没有消息传递回来,一切都不在与发送方有任何关联。这样也保证了,我们不需要在共享环境中与同步锁,互斥体等常用基础多线程元素打交道。 

    --------------------- 

    作者:无鞋童鞋 

    来源:CSDN 

    原文:https://blog.csdn.net/FX677588/article/details/74359823 

    版权声明:本文为博主原创文章,转载请附上博文链接!

     

     

    这篇文章讲解了如何使用netmq来实现个简单的actor,同时也讲解了actor model的基本概念,与共享内存模型的区别

    https://github.com/zeromq/netmq/blob/master/docs/actor.md

     

    actor模型与CSP模型

    https://www.jdon.com/concurrent/actor-csp.html

     

    卧槽,ROS的主题就是CSP模型中的CHANNEL!!!

    Actor模型和CSP模型的区别

    Akka/Erlangactor模型与Go语言的协程Goroutine与通道Channel代表的CSP(Communicating Sequential Processes)模型有什么区别呢?

    首先这两者都是并发模型的解决方案,我们看看Actor和Channel这两个方案的不同:

    Actor模型

    在Actor模型中,主角是Actor,类似一种worker,Actor彼此之间直接发送消息,不需要经过什么中介,消息是异步发送和处理的:

    actor模型

    Actor模型描述了一组为了避免并发编程的常见问题的公理:

    1.所有Actor状态是Actor本地的,外部无法访问。

    2.Actor必须只有通过消息传递进行通信。

    3.一个Actor可以响应消息:推出新Actor,改变其内部状态,或将消息发送到一个或多个其他参与者。

    4.Actor可能会堵塞自己,Actor不应该堵塞它运行的线程。

    更多可见Actor模型专题

     

    Channel模型

    Channel模型中,worker之间不直接彼此联系,而是通过不同channel进行消息发布和侦听。消息的发送者和接收者之间通过Channel松耦合,发送者不知道自己消息被哪个接收者消费了,接收者也不知道是哪个发送者发送的消息。

    channel模型

    Go语言的CSP模型是由协程Goroutine与通道Channel实现:

    • Go协程goroutine: 是一种轻量线程,它不是操作系统的线程,而是将一个操作系统线程分段使用,通过调度器实现协作式调度。是一种绿色线程,微线程,它与Coroutine协程也有区别,能够在发现堵塞后启动新的微线程。
    • 通道channel: 类似Unix的Pipe,用于协程之间通讯和同步。协程之间虽然解耦,但是它们和Channel有着耦合。

     

    Actor模型和CSP区别

    Actor模型和CSP区别图如下:

    ErIang  в

    Actor之间直接通讯,而CSP是通过Channel通讯,在耦合度上两者是有区别的,后者更加松耦合。

    同时,它们都是描述独立的流程通过消息传递进行通信。主要的区别在于:在CSP消息交换是同步的(即两个流程的执行"接触点"的,在此他们交换消息),而Actor模型是完全解耦的,可以在任意的时间将消息发送给任何未经证实的接受者。由于Actor享有更大的相互独立,因为他可以根据自己的状态选择处理哪个传入消息。自主性更大些。

    在Go语言中为了不堵塞流程,程序员必须检查不同的传入消息,以便预见确保正确的顺序。CSP好处是Channel不需要缓冲消息,而Actor理论上需要一个无限大小的邮箱作为消息缓冲。

    https://www.cnblogs.com/feng9exe/p/10482436.html

    源于从Erlang到Go的一些思维碰撞,就像当初从C++到Erlang一样,整理下来记于此。

    Actor

    Actor模型,又叫参与者模型,其”一切皆参与者(actor)”的理念与面向对象编程的“一切皆是对象”类似,但是面向对象编程中对象的交互通常是顺序执行的(占用的是调用方的时间片,是否并发由调用方决定),而Actor模型中actor的交互是并行执行的(不占用调用方的时间片,是否并发由自己决定)

    在Actor模型中,actor执行体是第一类对象,每个actor都有自己的ID(类比人的身份证),可以被传递。actor的交互通过发送消息来完成,每个actor都有一个通信信箱(mailbox,本质上是FIFO消息队列),用于保存已经收到但尚未被处理的消息。actorA要向actorB发消息,只需持有actorB ID,发送的消息将被立即Push到actorB的消息信箱尾部,然后返回。因此Actor的通信原语是异步的。

    从actor自身来说,它的行为模式可简化为:

    • 发送消息给其它的actor
    • 接收并处理消息,更新自己的状态
    • 创建其它的actor

    一个好的Actor模型实现的设计目标:

    • 调度器: 实现actor的公平调度
    • 容错性: 具备良好的容错性和完善错误处理机制
    • 扩展性: 屏蔽actor通信细节,统一本地actor和远程actor的通信方式,进而提供分布式支持
    • 热更新? (还没弄清楚热更新和Actor模型,函数式范式的关联性)

    在Actor模型上,Erlang已经耕耘三十余载,以上提到的各个方面都有非常出色的表现,其OTP整合了在Actor模型上的最佳实践,是Actor模型的标杆。

    CSP

    顺序通信进程(Communicating sequential processes,CSP)和Actor模型一样,都由独立的,并发的执行实体(process)构成,执行实体间通过消息进行通信。但CSP模型并不关注实体本身,而关注发送消息使用的通道(channel),在CSP中,channel是第一类对象,process只管向channel写入或读取消息,并不知道也不关心channel的另一端是谁在处理。channel和process是解耦的,可以单独创建和读写,一个process可以读写(订阅)个channel,同样一个channel也可被多个process读写(订阅)。

    对每个process来说:

    • 从命名channel取出并处理消息
    • 向命名channel写入消息
    • 创建新的process

    Go语言并没有完全实现CSP理论(参见知乎讨论),只提取了CSPprocesschannel的概念为并发提供理论支持。目前Go已经是CSP的代表性语言。

    CSP vs Actor

    • 相同的宗旨:”不要通过共享内存来通信,而应该通过通信来共享内存”
    • 两者都有独立的,并发执行的通信实体
    • Actor第一类对象为执行实体(actor)CSP第一类对象为通信介质(channel)
    • Actor中实体和通信介质是紧耦合的,一个Actor持有一个Mailbox,而CSPprocesschannel是解耦的,没有从属关系。从这一层来说,CSP更加灵活
    • Actor模型中actor是主体,mailbox是匿名的,CSP模型中channel是主体,process是匿名的。从这一层来说,由于Actor不关心通信介质,底层通信对应用层是透明的。因此在分布式和容错方面更有优势

    Go vs Erlang

    • 以上 CSP vs Actor
    • 均实现了语言级的coroutine,在阻塞时能自动让出调度资源,在可执行时重新接受调度
    • gochannel是有容量限制的,因此只能一定程度地异步(本质上仍然是同步的)erlangmailbox是无限制的(也带来了消息队列膨胀的风险),并且erlang并不保证消息是否能到达和被正确处理(但保证消息顺序),是纯粹的异步语义,actor之间做到完全解耦,奠定其在分布式和容错方面的基础
    • erlang/otpactor上扩展了分布式(支持异质节点),热更和高容错,go在这些方面还有一段路要走(受限于channel,想要在语言级别支持分布式是比较困难的)
    • go在消息流控上要做得更好,因为channel的两个特性: 有容量限制并独立于goroutine存在。前者可以控制消息流量并反馈消息处理进度,后者让goroutine本身有更高的处理灵活性。典型的应用场景是扇入扇出,Boss-Worker等。相比goerlang进程总是被动低处理消息,如果要做流控,需要自己做消息进度反馈和队列控制,灵活性要差很多。另外一个例子就是erlangreceive操作需要遍历消息队列(参考),而如果用go做同步调用,通过单独的channel来做则更优雅高效

    Actor in Go

    在用Go写GS框架时,不自觉地会将goroutine封装为actor来使用:

    • GS的执行实体(如玩家,公会)的逻辑具备强状态和功能聚合性,不易拆分,因此通常是一个实体一个goroutine
    • 实体接收的逻辑消息具备弱优先级,高顺序性的特点,因此通常实体只会暴露一个Channel与其它实体交互(结合go的interface{}很容易统一channel类型),这个channel称为RPC channel,它就像这个goroutine的ID,几乎所有逻辑goroutine之间通过它进行交互
    • 除此之外,实体还有一些特殊的channel,如定时器,外部命令等。实体goroutine对这些channel执行select操作,读出消息进行处理
    • 加上goroutine的状态数据之后,此时的goroutine的行为与actor相似:接收消息(多个消息源),处理消息,更新状态数据,向其它goroutine发送消息(通过RPC channel)

    到目前为止,goroutine和channel解耦的优势并未体现出来,我认为主要的原因仍然是GS执行实体的强状态性和对异步交互流程的顺序性导致的。

    在研究这个问题的过程中,发现已经有人已经用go实现了Actor模型: https://github.com/AsynkronIT/protoactor-go。 支持分布式,甚至supervisor,整体思想和用法和erlang非常像,真是有种他山逢知音的感觉。:)

    参考:

    1. http://jolestar.com/parallel-programming-model-thread-goroutine-actor/
    2. https://www.zhihu.com/question/26192499

     

    http://wudaijun.com/2017/05/go-vs-erlang/

    //--------------------------------------------------------------------------------------------- 合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。 积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇鳝之穴无可寄托者,用心躁也。


  • 相关阅读:
    postman的几个问题
    服了这个所谓北大青鸟官方学员社区论坛
    Gatling实战(三)
    Gatling实战(二)
    Gatling实战(一)
    httplib和urllib2常用方法
    jmeter的新增函数说明
    windows版jmeter的body data如何用 作为“换行”
    linux下oracle服务启动关闭
    linux下ORACLE监听日志的正确删除步骤
  • 原文地址:https://www.cnblogs.com/lizhensheng/p/11117459.html
Copyright © 2011-2022 走看看