Jeśli rozumiem, model aktora jest podobny do modelu obiektowego, ale z kilkoma różnicami:
- KAŻDY obiekt spawnuje swój własny wątek i nie stanowi problemu, nawet jeśli masz tysiące obiektów.
- Aktorzy nie wchodzą w interakcje, wywołując funkcje i zwracając wartości, ale zamiast tego wysyłając i odbierając wiadomości.
- Jeśli nie naruszysz tego modelu, Twoja aplikacja będzie korzystała z pełnej współbieżności bez ryzyka warunków wyścigowych.
- Wszystko, co możesz zrobić w OO, możesz zrobić z aktorami, ale lepiej, problem polega na tym, że wszystko, co zakodowaliśmy w ostatnich latach, było oparte na OO - ale przejście jest nieuchronne.
Załóżmy na przykład, że muszę zdefiniować klasę / aktora wektora 3d, utworzyć dwie instancje i wywołać na nich operację sumowania.
OBIEKT ZORIENTOWANY:
class V3d {
constructor V3d(x,y,z) //bla
float x,y,z;
function sum(V3d b)
{
return V3d(x+b.x,y+b.y,z+b.z);
}
}
//using:
mySum = V3d(1,2,3).sum(V3d(3,2,1)) //creates 2 instances, sum, returns instantly
drawPoint(mySum) //uses the result
MODEL AKTORA:
actor V3d
{
constructor V3d(x,y,z) //bla
float x,y,z;
loop
{
receive 'sum',b:V3d :
send(caller,'sumResult',V3d(x+b.x,y+b.y,z+b.z))
}
}
//using:
send(V3d(1,2,3),'sum',V3d(3,2,1)) //creates 2 instances, send to the first one a request to sum with the second one
loop
{
receive 'sumResult',result:
drawPoint(result) //receives result and draws it
}
Czy to to? Czy też całkowicie się mylę?
Odpowiedzi:
Krótka odpowiedź brzmi: nie, to nieprawda.
zaczyna się w miarę poprawnie (każdy aktor przynajmniej potencjalnie wykonuje jako niezależny wątek), ale potem w dużej mierze znika z szyn. W modelu nie ma nic, co sprawia, że wiele wątków działa dobrze - to zależy od implementacji. Co najwyżej łatwość tworzenia dużej liczby wątków wywiera presję na implementację w celu zapewnienia wydajnego wątkowania. Przynajmniej jeśli chodzi o model, wszelkie podobieństwo między aktorami a przedmiotami jest w większości przypadkowe. „Obiekt” niesie ze sobą dość konkretne implikacje dotyczące sposobu łączenia kodu i danych. Aktor na ogół będzie zawierał zarówno kod, jak i dane, ale niewiele sugeruje, w jaki sposób są one łączone (poza faktem, że jedynymi danymi widocznymi dla świata zewnętrznego są wiadomości).
Zazwyczaj opisywanie interakcji to wysyłanie wiadomości, tak. Nie mam przydatnego cytatu, ale ktoś już dawno udowodnił, że mechanizmy takie jak funkcje wirtualne C ++ są izomorficzne w wysyłaniu wiadomości (ponieważ funkcje wirtualne są zwykle implementowane, używasz przesunięcia w vtable - ale jeśli zamiast tego wysłał przesunięcie do tabeli komunikatów, efekt byłby taki sam).
To nie jest takie proste. Jeśli potrafisz znaleźć kopię, Henry Baker (z kimś, kogo obecnie nie pamiętam) napisał artykuł o zasadach niezbędnych do zachowania spójności danych w modelu aktorskim.
„Lepszy” jest co najwyżej wysoce subiektywny. Niektóre problemy mają charakter bardzo równoległy i naprawdę obejmują dużą liczbę zasadniczo autonomicznych jednostek, przy minimalnej interakcji, która jest przede wszystkim asynchroniczna. W takim przypadku model aktora może naprawdę działać bardzo dobrze. W przypadku innych problemów tak naprawdę nie jest. Niektóre problemy mają prawie całkowicie szeregowy charakter. Inne mogą być wykonywane równolegle, ale nadal wymagają ścisłej synchronizacji między tymi czynnościami (np. Zasadniczo tryb podobny do SIMD, w którym wykonuje się jedną instrukcję na raz, ale każda instrukcja działa na dużą liczbę elementów danych). Z pewnością możliwe jest rozwiązanie obu tych problemów za pomocą modelu aktora - ale w przypadku takich problemów często wymaga to sporo dodatkowej pracy za niewielką lub żadną korzyść.
źródło
Odnośnie 1: Pracowałem z aplikacją modelowaną przez aktora z jednym wątkiem (ish), więc całkiem możliwe jest zignorowanie dużej liczby wątków, które to sugeruje. AFAIK, nici nie są lekkimi przedmiotami w żaden sposób, więc prawdopodobnie nie jest pożądane, aby mieć jeden dla każdego aktora, w zależności od liczby aktorów, których używasz.
Odnośnie 3: Jestem całkiem pewien, że warunki wyścigu mogą się zdarzyć w systemach modelowanych przez aktorów po prostu z powodu logiki programowania?
Odnośnie 4: Zdefiniować „lepiej”? Z mojego doświadczenia wynika, że logika asynchroniczna może być znacznie trudniejsza do odczytania niż rzeczy synchroniczne. np. w powyższym przykładzie nie wiesz, która operacja jest odpowiedzialna za wynik, więc musisz wykonać dodatkowe śledzenie wiadomości. Po dodaniu i włączeniu i wyłączeniu innych komunikatów w logice intencja kodu rozłożona jest na kilka funkcji wysyłania / odbierania.
Powiedziawszy to wszystko, jestem wielkim fanem wykorzystania modelu aktora do wyższych warstw aplikacji. Może to ułatwić odsprzęganie, ponieważ dodawanie zależności jest nieco trudniejsze niż dodawanie funkcji. Nie mam też dużego doświadczenia z językiem wyższym niż języki Java, a inne paradygmaty mogą wspierać asynchroniczność w bardziej fundamentalny sposób.
źródło