This question décrit quels acteurs sont dans la programmation d'acteur. Quels sont les messages? Comment pouvez-vous éviter l'état partagé si vous envoyez un objet dans un message (en supposant que des objets existent dans la programmation d'acteur)?Quels sont les messages dans la programmation d'acteur?
Répondre
Si nous pensons que les acteurs sont des personnes, alors les messages sont comme ... des messages. Dites à un patron de faire la racine carrée d'une liste de nombres a
, et ne voulez pas faire tout le calcul moi-même. Il peut embaucher des travailleurs, et le patron connaîtra leurs numéros de téléphone. Par conséquent, le Patron envoie un message SMS à chacun des Travailleurs et leur dit de "trouver la racine carrée de a_i
et de me répondre au 555-1234 après que vous ayez terminé.". Cette instruction est un message. Le Patron attend alors que les Travailleurs finissent. Une fois que les travailleurs ont terminé le calcul, ils enverront un message de retour au boss et rapporteront les résultats. Ceci est également fait dans le passage de message.
+------+ set_result(i=0, val=3) +------------+
| Boss | <------------------------ | Worker 0 |
+------+ +------------+
^set_result(i=1, val=4) +------------+
‘--------------------------- | Worker 1 |
+------------+
....
Cela ressemble à la programmation orientée objet, mais il n'y a pas d'ordre auquel lorsqu'un message est envoyé ou reçu - ils sont passés de manière asynchrone. (Cependant, au sein de l'acteur eux-mêmes, les messages sont reçus et mis en attente de manière synchrone.)
Lorsque écrit dans le code, il peut être comme
actor Boss:
receive('run'):
worker_addrs = spawn_many(SqrtWorker, len(a)) # hire workers.
for i, addr in enumerate(worker_addrs):
send(addr, 'sqrt', reply_addr=self, i=i, a_i=a[i])
receive('set_value', i, val):
a[i] = val
actor SqrtWorker:
receive('sqrt', reply_addr, i, a_i):
send(reply_addr, 'set_value', i, sqrt(a_i))
quit()
Il n'y a pas de « problème des états partagés », parce qu'un l'état ne peut pas être partagé sans copie. Dans mon exemple ci-dessus, les éléments de la liste a
sont copiés pour chaque travailleur. En fait, seul le Boss connaît l'existence de a
- il s'agit d'un état local.
Maintenant, que faire si nous voulons vraiment faire a
partagé? Dans le modèle d'acteur, nous les convertirions en un nouvel acteur, et le numéro de téléphone de cet acteur serait envoyé au travailleur.
+------+ sqrt(i=0, a_phoneNum=555-1111) +----------+
| Boss | -------------------------------> | Worker 0 |
+------+ +----------+
+---+
| a |
+---+
Le travailleur a alors demander à l'acteur de liste pour les informations requises (il est possible parce que le patron a donné le numéro de téléphone du a
au travailleur.)
+------+ +----------+
| Boss | | Worker 0 |
+------+ +----------+
|
+---+ |
| a | <---------------------------’
+---+ get(i=0)
Quelque temps plus tard, les des réponses de la liste ...
+------+ +----------+
| Boss | | Worker 0 |
+------+ +----------+
^
+---+ list_val(i=0, val=9) |
| a | ----------------------------’
+---+
alors que le travailleur peut calculer la racine carrée après avoir reçu le message list_val
.
+------+ set_result(i=0, val=3) +----------+
| Boss | <------------------------------ | Worker 0 |
+------+ +----------+
+---+
| a |
+---+
Le patron met à jour enfin l'état partagé
+------+ +----------+
| Boss | | Worker 0 |
+------+ +----------+
| set(i=0, val=3)
| +---+
‘------> | a |
+---+
qu'il y aura des problèmes d'accès à l'état partagé comme celui-ci? Non - étant donné que les messages reçus par a
doivent être exécutés de manière synchrone, toutes les actions de lecture/écriture seront interférées entre elles. Ainsi, il n'est pas nécessaire de jouer avec les mutex.