O modelo de ator opera na passagem de mensagens. Os processos individuais (atores) podem enviar mensagens de forma assíncrona entre si. O que distingue isso do que normalmente pensamos como o modelo de threading é que não há (pelo menos em teoria) nenhum estado compartilhado. E se alguém acredita (com razão, eu acho) que o estado compartilhado é a raiz de todo o mal, então o modelo do ator se torna muito atraente.
Não devemos ficar muito animados, no entanto. O modelo de ator não torna (ao contrário de algumas alegações) impossível ter deadlocks. O modelo de ator também não impede que você tenha contenção de recursos entre diferentes processos - filas de mensagens, por exemplo. O modelo só é "livre de bloqueio" acima de um certo nível. Em um nível inferior, para coordenar as filas de mensagens, o bloqueio ainda é necessário.
Um tópico não pode ser visto como um ator e enviar mensagens para outros tópicos?
Bem, sim e não. Não, se você estiver usando apenas a abordagem de colocar mutexes em locais de memória compartilhada. Em seguida, os threads compartilham esse estado - ambos têm acesso a essa memória, podem tanto ler, reescrever, etc. Mas você pode construir um modelo de ator em cima de um modelo de threading e, de fato, todas as implementações de ator têm threads por baixo. Eu hackeei algo assim (muito mal), dando a cada thread uma fila protegida por um mutex - apenas por diversão. Para ter uma ideia de como a impedância do thread do ator é gerenciada, veja minha pergunta de um ano atrás .
Posso usar o Actor Model em qualquer idioma usando threads de maneira diferente?
Sim, mas vai dar mais trabalho. Seu idioma favorito pode muito bem ter uma biblioteca de passagem de mensagens, então isso seria a primeira coisa a investigar. Além disso, você deve investigar o uso de estruturas de dados imutáveis. Observe que se uma estrutura de dados é imutável, então você essencialmente lidou com o problema do "estado compartilhado" - vários threads podem conter referências a dados imutáveis sem que nada de ruim aconteça. Há uma razão pela qual as linguagens de ator tendem a também ser linguagens funcionais (erlang, scala).
Você também pode querer dar uma olhada em Software Transactional Memory, que é um modelo diferente, mas também atraente. Clojure é meu exemplo favorito disso.
Eu não diria que os atores sempre passam mensagens de forma assíncrona - isso seria muito lento. Caso em questão, o projeto JActor usa mensagens bidirecionais (solicitação / resposta) para modelar melhor uma chamada de método. E a maioria das solicitações são atendidas de forma síncrona.
JActor (uma biblioteca Java) também não usa bloqueios. Apenas algumas estruturas de dados atômicas e simultâneas, com alguns semáforos inseridos. A passagem de mensagens é de cerca de 0,8 bilhões de mensagens por segundo.
https://github.com/laforge49/JActor
fonte