Se eu entendi, o modelo de ator é exatamente como o modelo de objeto, mas com algumas diferenças:
- CADA objeto gera sua própria thread separada e não é um problema, mesmo quando você tem milhares de objetos.
- Os atores não interagem chamando funções e obtendo valores de retorno, mas enviando e recebendo mensagens.
- Se você não violar esse modelo, seu aplicativo usará a simultaneidade em todo o seu potencial sem riscos de condições de corrida.
- 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?
Respostas:
A resposta curta é não, não está correta.
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).
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).
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.
"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.
fonte
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.
fonte