Actor model


 

 

C++ Actor框架

 

http://www.aiuxian.com/relative/p-1940333.html

通過akka, erlang來了解actor模型

c++並發編程的一種思維

使用筆記博客

https://www.cnblogs.com/zhejiangxiaomai/p/5257057.html

https://blog.csdn.net/woshiyuanlei/article/details/51276369

actor模型的優缺點分析

 

0x00 前言

一般來說有兩種策略用來在並發線程中進行通信:共享數據和消息傳遞。熟悉c和java並發編程的都會比較熟悉共享數據的策略,比如java程序員就會常用到java.util.concurrent包中同步、鎖相關的數據結構。

 

使用共享數據方式的並發編程面臨的最大的一個問題就是數據條件競爭(data race)。處理各種鎖的問題是讓人十分頭痛的一件事。

 

和共享數據方式相比,消息傳遞機制最大的優點就是不會產生數據競爭狀態(data race)。實現消息傳遞有兩種常見的類型:基於channel的消息傳遞和基於Actor的消息傳遞。本文主要是來分享Scala的Actor模型。

 

文章結構

本篇博客嘗試講解Actor模型。由於目前Scala的使用頻率較高,因此主要語言為Scala

 

主要分為下面幾個部分:

Actor模型的基本概念使用

講一下akka框架中scala的基本使用,主要提幾個重要的api

寫幾個例子幫助理解 

1. HelloWorld 簡單版:通過這個例子來簡單看一下AkkaActor的使用 

2. HelloWordl 進階版:稍微進化了一點點,多了preStartPoisonPill的使用。 

3. WordCount 偽分布式:一個單機版的wordcount,一個map,多個reduce。后續再補充完全分布式的程序。

0x01 基本概念

Actor是計算機科學領域中的一個並行計算模型,它把actors當做通用的並行計算原語:一個actor對接收到的消息做出響應,進行本地決策,可以創建更多的actor,或者發送更多的消息;同時准備接收下一條消息。

 

在Actor理論中,一切都被認為是actor,這和面向對象語言里一切都被看成對象很類似。但包括面向對象語言在內的軟件通常是順序執行的,而Actor模型本質上則是並發的。

 

什么是Actor模型

Actor的概念來自於Erlang,在AKKA中,可以認為一個Actor就是一個容器,用以存儲狀態、行為、Mailbox以及子ActorSupervisor策略。Actor之間並不直接通信,而是通過Mail來互通有無。

 

每個Actor都有一個(恰好一個)Mailbox。Mailbox相當於是一個小型的隊列,一旦Sender發送消息,就是將該消息入隊到Mailbox中。入隊的順序按照消息發送的時間順序。Mailbox有多種實現,默認為FIFO。但也可以根據優先級考慮出隊順序,實現算法則不相同。

 

消息和信箱

異步地發送消息是用actor模型編程的重要特性之一。消息並不是直接發送到一個actor,而是發送到一個信箱(mailbox)。如下圖。

 

這樣的設計解耦了actor之間的關系——actor都以自己的步調運行,且發送消息時不會被阻塞。雖然所有actor可以同時運行,但它們都按照信箱接收消息的順序來依次處理消息,且僅在當前消息處理完成后才會處理下一個消息,因此我們只需要關心發送消息時的並發問題即可。

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

作者:木東居士 

來源:CSDN 

原文:https://blog.csdn.net/zhaodedong/article/details/73441303 

版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

 

https://blog.csdn.net/kjfcpua/article/details/8147850

 

其他c++ actor庫

orca

https://segmentfault.com/a/1190000016955361?utm_source=tag-newest

theron

https://blog.csdn.net/FX677588/article/details/74936625

http://www.mahaixiang.cn/bcyy/954.html

 

actormodel概念介紹,這個文章比較好,講了actorrpcmq系統的一點點聯系

http://www.sohu.com/a/306231390_684445

回去好好看看,總結!

https://blog.csdn.net/yongche_shi/article/details/51523688

 

https://stackoverflow.com/questions/51904706/check-whether-a-detached-pthread-is-still-alive/51915501?r=SearchResults#51915501

對於使用actor model的建議

問題說,需要一個獨立的線程,detached。

說自己使用c++,問為什么不用c++的標准線程庫,然后說大家都在用pthread,而且切換到C時候也不用改代碼

然后推薦用條件變量

 

然后的一個回答就有深度了,推薦使用actor model,然后在回答中說。

如果你想讓一些線程獨立工作並且不管它,那么適合使用actor model。介紹說0mqsocket其實不僅僅是unix socket,也可以是tcp socketipcimprocess-transfer,但是行為都是一致的,而且,in-proc memory transfer真的很快

Actor modelCSP Communicating Sequential Processes)的區別就是。在actor模式中,當一個消息送達,sender不會受到額外信息。但是在CSP中,一個成功的send,需要接收方收到消息並且讀取消息。

在實踐actorCSP編程中,不要混用各種並發機制,即不要使用共享內存,信號,條件變量等其他機制,非常容易混淆。(z項目已經徹底腐壞)

A------Have you thought about using Actor model programming, or even better Communicating Sequential Processes?

These are really quite a good model for when you have a separate thread that needs to go off and do its own thing, and you need to be able to tell it something and get an answer back.

Your apparent need is to know that something asynchronous has completed (the termination of a separate thread) - there's nothing wrong with having that thread send you a direct acknowledgement of it's termination, rather than trying to have to determine whether or not it's still alive through slightly iffy means such as waitpid(). So say you chose ZeroMQ as your Actor model library; to "kill" that detached thread you'd send it a command down a ZeroMQ "socket". The recipient thread would receive that message, understand that it means "die", and do whatever clean up it needs to before terminating itself. Just before it terminates itself, it sends you back an acknowledgement on another "socket" that yes, it is dead (or at least about to be so, all necessary cleanup has already happened).

Actor model / CSP programming places an emphasis on having a loop responding to messages from one or more sources. Well, your own code snippet hints at a loop, waiting for the pthread_cancel()to take effect.

I've put "socket" in quotes as underneath a ZeroMQ socket can be a tcp socket, ipc, some in-process memory transfer, etc; it all behaves the same. In-proc is, naturally, quite quick.

The difference between Actor model and Communicating Sequential Processes is that in Actor model, when a message is sent there is no information available to the sender that it has been received, whilst in Communicating Sequential Processes a successful send = a completed read. Personally speaking I prefer the latter - your code then has complete knowledge as to where a message recipient has got to; a send/receive are an Execution Rendezvous. So when you send the "terminate" message, you know for sure that the recipient thread has received the message and is now acting on it. When the recipient sends it's "I'm dead" acknowledgement, it knows that the command thread has received that ack.

FYI, CSP is very useful in real time systems, not because it's faster but because your program can have much better knowledge as to whether it's kept up with the real time demand or not. Actor model lets you "hide" real time inadequacies as latency in communications links.

Thank you for answering the actual question and for the great advice. Jonathan Lee Aug 19 '18 at 18:50

@JonathanLee, no worries, good luck! Be aware that if you are going to go with Actor model or CSP programming, it's best if you go the whole way. That is, don't try and casually mix it with shared memory, signals, or condition variables; it can get horribly confusing (especially signals; yeurk!). That total conversion might be a major revision to the architecture of your application, so it's worth doing some reading and careful thinking about the architecture. As you're detaching a thread I suspect that actually there's not too much data being shared between them, so perhaps it's not too bad. bazza Aug 20 '18 at 23:45

@JonathanLee, p.s. good reading material for ZeroMQ can be found by searching for the ZeroMQ guide. bazza Aug 20 '18 at 23:46

@JonathanLee, p.p.s. (sorry!), CSP is making something of a comeback. Both Rust and Golang have it as part of the language. Rust in particular is looking very good, with many of the beneficial aspects of C++ plus a whole load of strict memory safety thingies (you can tell I've not started learning it yet...). I suspect that the CSP is a side effect of the way it controls memory, much as CSP involves "copying" data from A to B; passing "ownership" of data from A to B achieves much the same thing without the actual copying taking place. bazza Aug 20 '18 at 23:48 

 

 

 

Q----I am working with POSIX threads for a multi-threaded socket programming project. I have run into a situation where I need to detach a thread from the main program using setdetachstate(); however, later on I cancel the thread (I know that cancelling is generally bad practice, but I know what I'm doing (hopefully)). I need a method to check whether the thread is still alive or not, and after doing a bit of research, I found that waitpid() might work for my purposes even though I have a TID instead of a PID. However, after trying it out, both with and without ptraces, it didn't work. Another method that I have seen on the Internet everywhere is pthread_join(). While I agree that it is the optimal way to do it, as I said, my thread is detached, so it can't be joined.

As a side note, my goal is to find a way to wait for the function call pthread_cancel() to finish before executing any subsequent code, i.e.

pthread_t tid; // ... pthread_cancel(tid); // wait until pthread with ID tid is cancelled // more code here...

Originally, the reason why I need to check whether the detached pthread is alive was because I was planning on doing something like this: while(!pthread_dead(tid)); or something of this manner; however, if there is a solution that directly waits for the cancel to finish, that would be even better. Please try not to criticize my use of detached threads or pthread cancelling; I have contemplated many plans of action and this seems to be required no matter how I go about it (unless I'm doing a multiprocessed application, which I don't want to do). Unless I'm doing something absolutely syntactically or structurally abominable, I would appreciate it if you just answered my question.

Thank you!

P.S. I'm coding in C++.

 

"P.S. I'm coding in C++." So why not using the C++ standard threading facilities instead of native pthread funcitonality? πάντα ε Aug 18 '18 at 2:23

άνταε It seems that pthreads are used the most in C++ socket programming, at least in the books and people that I've talked to. And, I think it has better documentation and community than std::thread. There was a time that I was thinking of using it though. Also, if I ever go back to C for some reason or another, I won't have to change it. Jonathan Lee Aug 18 '18 at 2:26 

Did you consider using a condition variable to negotiate the termination of the thread? Galik Aug 18 '18 at 2:33

@JonathanLee Regarding documentation I can't agree with your argument. The native pthread lib implementations might consider some specific OS functionality but usually isn't abstract enough to exhaust any aspect of facilities the particular OS offers. I'd just rely on some good abstractions of synchronization mechanisms as the C++ standard library offers. πάντα ε Aug 18 '18 at 2:35 

2

A condition variable allows one thread to send signals to another thread that a condition has changed. Using a condition variable you can set a condition for the thread to stop and that thread can then signal you when it has completed. Galik Aug 18 '18 at 2:40

 

actor模型與DDD的一些思路碰撞

https://www.jdon.com/45516

>1.actor並發模型的應用場景?

 

適合有狀態或者稱可變狀態的業務場景,如果用DDD術語,適合聚合根,具體案例如訂單,訂單有狀態,比如未付款未發貨,已經付款未發貨,已付款已發貨,導致訂單狀態的變化是事件行為,比如付款行為導致頂大狀態切換到"已經付款未發貨"。

 

如果知曉GOF設計模式的狀態模式,就更好理解有態概念。

 

2.actor的原理?思維方式改變?

 

行為導致狀態變化,行為執行是依靠線程,比如用戶發出一個付款的請求,服務器后端派出一個線程來執行付款請求,攜帶付款的金額和銀行卡等等信息,當付款請求被成功完成后,線程還要做的事情就是改變訂單狀態,這時線程訪問訂單的一個方法比如changeState。

 

如果后台有管理員同時修改這個訂單狀態,那么實際有兩個線程共同訪問同一個數據,這時就必須鎖,比如我們在changeState方法前加上sychronized這樣同步語法。

 

使用同步語法壞處是每次只能一個線程進行處理,如同上廁所,只有一個蹲坑,人多就必須排隊,這種情況性能很低。

 

如何避免鎖?

 

避免changeState方法被外部兩個線程同時占用訪問,那么我們自己設計專門的線程守護訂單狀態,而不是普通方法代碼,普通方法代碼比較弱勢,容易被外部線程hold住,而我們設計的這個對象沒有普通方法,只有線程,這樣就變成Order的守護線程和外部訪問請求線程的通訊問題了。

 

Actor采取的這種類似消息機制的方式,實際在守護線程和外部線程之間有一個隊列,俗稱信箱,外部線程只要把請求放入,守護線程就讀取進行處理。

 

這種異步高效方式是Actor基本原理,以ERlang和Scala語言為主要特征,他們封裝得更好,類似將消息隊列微觀化了。

 

我個人認為要使用好Actor,還是要樹立自己對有態和無態的敏感性,這是幾年前我宣傳EJB的有態和無態Bean強調的一點,如果沒有這個敏感性,按照DDD第一找出聚合根的分析方法也能抓住重點。

 

當然這些思維的前提是拋棄數據庫中心思維,不要老是想着把狀態存在數據庫中,然后用SQL不斷修改,這是很低效的,也是有鎖,比Java等語言的同步鎖性能更差。

 

以我個人來說經歷的步驟如下:

 

1.用數據表一個字段來表示狀態,比如1表示已付款未發貨,2表示已付款已發貨,然后用戶來一個請求用SQL修改。

 

2.ORM實現,比如Hibernate JPA來修改狀態,雖然不用SQL了,但是Hibernate的悲觀鎖和樂觀鎖也讓人抓狂。

 

3.徹底拋棄數據庫,直接在內存緩存中進行修改,使用Java的同步鎖,性能還是不夠,吞吐量上不去。

 

4.Actor模型。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM