3

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

4

1 回答 1

9

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

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

所以老板会给每个工人发短信,告诉他们“求平方根a_i;完成后回复我555-1234”。该指令是一条消息。然后,Boss 将等待工人完成。

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

Worker 完成计算后,会向 Boss 发送一条短信并报告结果。这也在消息传递中完成。

 +------+   set_result(i=0, val=3)  +------------+
 | Boss | <------------------------ | Worker 0   |
 +------+                           +------------+
       ^  set_result(i=1, val=4)    +------------+
       ‘--------------------------- | Worker 1   |
                                    +------------+
                                       ....

这听起来像面向对象的编程,但是发送或接收消息时没有顺序 - 它们是异步传递的。(然而,在actor内部,消息是同步接收和排队的。)

当用代码编写时,它可能像

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共享怎么办?在actor模型中,我们会将它们转换为一个新的actor,并将这个actor的电话号码发送给Worker。

 +------+  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 | ----------------------------’
             +---+

那么 Worker 收到消息后就可以计算平方根了list_val

 +------+     set_result(i=0, val=3)      +----------+
 | Boss | <------------------------------ | Worker 0 |
 +------+                                 +----------+

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

Boss终于更新了共享状态

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

像这样访问共享状态会有什么问题吗?不——由于接收到的消息a必须同步运行,所有读/写操作都会相互干扰。因此没有必要弄乱互斥锁。

于 2010-06-11T11:08:20.453 回答