Если мы думаем, что актеры - Люди, тогда сообщения похожи на ... сообщения.
Скажем, Босс хочет получить квадратный корень из списка чисел a
и не хочет делать всевычисляя себя.Он может нанять нескольких Рабочих, и Босс узнает их телефонные номера.
Поэтому Босс отправит СМС каждому из Рабочих и скажет им: «Найти квадратный корень из a_i
; ответьте мне на 555-1234 после того, как ты это сделал.Эта инструкция является сообщением .Затем босс будет ждать окончания рабочих.
+------+ sqrt(i=0, a_i=9) +------------+
| Boss | ------------------------> | Worker 0 |
+------+ +------------+
| sqrt(i=1, a_i=16) +------------+
‘--------------------------> | Worker 1 |
+------------+
....
После того, как рабочие завершат вычисления, они отправят SMS-сообщение боссу и сообщат о результатах.Это также делается при передаче сообщений.
+------+ set_result(i=0, val=3) +------------+
| Boss | <------------------------ | Worker 0 |
+------+ +------------+
^ set_result(i=1, val=4) +------------+
‘--------------------------- | Worker 1 |
+------------+
....
Это звучит как объектно-ориентированное программирование, но нет порядка, в котором при отправке или получении сообщения они передаются асинхронно ,(Однако внутри самого субъекта сообщения принимаются и помещаются в очередь синхронно.)
При написании в коде это может выглядеть следующим образом:
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()
Нет проблем с общими состояниями", потому что состояние не может быть общим без копирования.В моем примере выше элементы списка a
копируются каждому работнику.Фактически, только Босс знает о существовании a
- это локальное состояние .
Теперь, что если мы действительно хотим сделать a
общим?В модели актера мы конвертируем их в нового актера, и номер телефона этого актера отправляется Рабочему.
+------+ sqrt(i=0, a_phoneNum=555-1111) +----------+
| Boss | -------------------------------> | Worker 0 |
+------+ +----------+
+---+
| a |
+---+
Рабочий затем запрашивает у актера списка необходимую информацию (это возможнопотому что босс дал номер телефона a
работнику.)
+------+ +----------+
| Boss | | Worker 0 |
+------+ +----------+
|
+---+ |
| a | <---------------------------’
+---+ get(i=0)
Через некоторое время список отвечает ...
+------+ +----------+
| Boss | | Worker 0 |
+------+ +----------+
^
+---+ list_val(i=0, val=9) |
| a | ----------------------------’
+---+
, тогда работник может вычислитьквадратный корень после получения сообщения list_val
.
+------+ set_result(i=0, val=3) +----------+
| Boss | <------------------------------ | Worker 0 |
+------+ +----------+
+---+
| a |
+---+
Босс наконец обновляет общее состояние
+------+ +----------+
| Boss | | Worker 0 |
+------+ +----------+
| set(i=0, val=3)
| +---+
‘------> | a |
+---+
Будут ли проблемы с доступом к общему состоянию, подобному этому?Нет - поскольку сообщения, полученные a
, должны выполняться синхронно, все действия чтения / записи будут мешать друг другу.Таким образом, нет необходимости связываться с мьютексами.