Minha descrição do modelo de ator está correta?


13

Se eu entendi, o modelo de ator é exatamente como o modelo de objeto, mas com algumas diferenças:

  1. CADA objeto gera sua própria thread separada e não é um problema, mesmo quando você tem milhares de objetos.
  2. Os atores não interagem chamando funções e obtendo valores de retorno, mas enviando e recebendo mensagens.
  3. Se você não violar esse modelo, seu aplicativo usará a simultaneidade em todo o seu potencial sem riscos de condições de corrida.
  4. Tudo o que você pode fazer no OO pode usar atores, mas melhor, o problema é que tudo o que codificamos nos últimos anos foi baseado no OO - mas uma transição é iminente.

Por exemplo, suponha que eu precise definir classe / ator de vetor 3d, criar duas instâncias e chamar uma operação de soma nelas.

ORIENTADO A OBJETO:

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

MODELO DO ATOR:

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
}

É isso? Ou estou completamente errado?


Atores leves ou microagentes ou componentes de fluxo de dados não usam necessariamente seu próprio encadeamento. :-) Verifique os seguintes termos: programação baseada em ator, programação baseada em agente, programação baseada em fluxo de dados. Eles são muito semelhantes, mas têm restrições diferentes. Ohh eu vou pedir isso como uma questão ;-)
inf3rno

Respostas:


12

A resposta curta é não, não está correta.

  1. começa razoavelmente correto (cada ator, pelo menos potencialmente, executa como um encadeamento independente), mas depois sai em grande parte dos trilhos. Não há nada sobre o modelo que faça com que muitos threads funcionem bem - isso depende da implementação. No máximo, a facilidade de criar muitos encadeamentos pressiona a implementação para fornecer threading eficiente. Pelo menos no que diz respeito ao modelo, qualquer semelhança entre atores e objetos é quase uma coincidência. "Objeto" traz implicações bastante específicas sobre como você combina código e dados. Um ator geralmente envolve código e dados, mas implica pouco sobre como eles são combinados (exceto o fato de que os únicos dados visíveis para o mundo externo são as mensagens).

  2. A maneira usual de descrever a interação é como o envio de mensagens, sim. Não tenho uma citação à mão, mas alguém já provou há muito tempo que mecanismos como funções virtuais C ++ são isomórficas para o envio de mensagens (como as funções virtuais são normalmente implementadas, você está usando um deslocamento em uma vtable - mas se você enviou um deslocamento para uma tabela de mensagens, o efeito seria o mesmo).

  3. Não é tão simples assim. Se você puder encontrar uma cópia, Henry Baker (com outra pessoa cujo nome não me lembro agora) escreveu um artigo sobre as regras necessárias para a consistência dos dados no modelo do ator.

  4. "Melhor" é altamente subjetivo, na melhor das hipóteses. Alguns problemas são altamente paralelos por natureza e realmente envolvem um grande número de entidades essencialmente autônomas, com interação mínima que é basicamente assíncrona. Nesse caso, o modelo do ator pode funcionar muito bem. Para outros problemas, esse não é realmente o caso. Alguns problemas são de natureza quase inteiramente serial. Outras podem ser executadas em paralelo, mas ainda requerem uma sincronização estreita entre essas ações (por exemplo, basicamente um modo SIMD, onde você executa uma instrução por vez, mas cada instrução atua em um grande número de itens de dados). Certamente, é possível resolver esses dois tipos de problemas usando o modelo de ator - mas, para esses problemas, geralmente envolve uma quantidade considerável de trabalho extra com pouco ou nenhum ganho em troca.


Não há relação entre o número de atores e o número de threads; o que o modelo de ator garante é que uma determinada instância seja operada apenas por um único encadeamento de cada vez, para que seus atores já estejam protegidos contra encadeamentos e você não precise usar estratégias de sincronização e bloqueio dentro deles.
Rob Crawford

@ RobCrawford: essa é uma maneira (bastante trivial) de garantir a consistência dos dados no modelo do ator. O artigo de Hewitt / Baker cobre mais possibilidades, como várias cópias de um ator rodando em tópicos separados (hmm ... olhando para minha resposta, estou imaginando se honestamente não conseguia lembrar o nome de Carl Hewitt na época, ou estava ser irônico quando eu escrevi).
Jerry Coffin

A assincronicidade da mensagem não é um elemento essencial do modelo? Isso certamente impediria que fosse isomórfico com chamadas de função virtual, que são de natureza síncrona. Ou a distinção é irrelevante de alguma perspectiva?
boycy

2

No que diz respeito a 1: trabalhei com um aplicativo modelado por ator (ish) com thread (ish), portanto é possível desconsiderar o grande número de threads que isso sugere. AFAIK, os encadeamentos não são objetos leves de forma alguma, portanto, provavelmente não é desejável ter um para cada ator, dependendo de quantos atores você está usando.

Em relação a 3: Tenho certeza de que condições de corrida podem acontecer em sistemas modelados por atores simplesmente devido à lógica de programação?

Em relação a 4: Definir 'melhor'? Minha experiência foi que a lógica assíncrona pode ser muito mais difícil de ler do que coisas síncronas. por exemplo, no seu exemplo acima, você não sabe qual operação é responsável por qual resultado, portanto, há um rastreamento extra de mensagens a ser realizado. Depois que ele é adicionado e outras mensagens são incluídas na lógica, a intenção do código é espalhada por várias funções de envio / recebimento.

Dito tudo isso, sou um grande fã do uso de modelos de atores nas camadas superiores de um aplicativo. Isso pode facilitar a dissociação, já que adicionar dependências é um pouco mais difícil do que adicionar uma função. Também não tenho muita experiência com nível superior às linguagens Java, e outros paradigmas podem oferecer suporte a assíncrono de maneira mais fundamental.


Em relação ao item 1: Bem, "thread" pode se referir a muitas coisas. Os threads do sistema operacional geralmente são bastante pesados, é verdade, mas existem tempos de execução de idioma que lidam internamente com centenas, milhares e até milhões de "threads" de execução em um pequeno número de threads do sistema operacional. Em algumas implementações, esses modelos aparentemente escalam até dezenas de núcleos (vi declarações de que as versões recentes do GHC funcionam bem com 32 núcleos).
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.