演员编程中的消息是什么?

时间:2010-06-11 09:25:18

标签: message actor

This question描述了演员编程中的演员。什么是消息?如果在消息中发送对象(假设在actor编程中存在对象),如何避免共享状态?

1 个答案:

答案 0 :(得分:9)

如果我们认为演员是人,那么消息就像......消息。

说老板想要对数字列表a的平方根进行平方,并且不想做所有的计算。他可以雇佣一些工人,老板会知道他们的电话号码。

所以老板会给每个工人发短信,告诉他们“找到a_i的平方根;在你做完之后回复我555-1234。”此说明是消息。然后Boss将等待工人完成。

 +------+  sqrt(i=0, a_i=9)         +------------+
 | Boss | ------------------------> | Worker 0   |
 +------+                           +------------+
       |   sqrt(i=1, a_i=16)        +------------+
       ‘--------------------------> | Worker 1   |
                                    +------------+
                                       ....

在工人完成计算后,他们将发送短信回到Boss并报告结果。这也是在消息传递中完成的。

 +------+   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的元素被复制到每个工作者。事实上,只有Boss知道a的存在 - 这是本地状态

现在如果我们真的希望共享a怎么办?在演员模型中,我们将它们转换为新演员,并将此演员的电话号码发送给工人。

 +------+  sqrt(i=0, a_phoneNum=555-1111)  +----------+
 | Boss | -------------------------------> | Worker 0 |
 +------+                                  +----------+

             +---+
             | a |
             +---+

然后,工作人员向列表演员询问所需信息(这是可能的,因为Boss已将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最终更新了共享状态

 +------+                                 +----------+
 | Boss |                                 | Worker 0 |
 +------+                                 +----------+
    | set(i=0, val=3)                
    |        +---+ 
    ‘------> | a | 
             +---+ 

访问这样的共享状态会有任何问题吗?否 - 由于a收到的消息必须同步运行,因此所有读/写操作都会相互干扰。因此,没有必要混淆互斥量。