1

我正在尝试制作带有进程的素数的 Erlang 程序(无效,我知道,但是嘿,这只是为了好玩:)) - 类似于numbersimulation.com的内容。

在每个“滴答”上,服务器都会产生新的进程(“数字”),它会增加其计数器。如果 counter == 该数字,这是一个因素,所以我们让服务器知道。如果服务器没有收到任何消息,则它是质数。

在小数字上(素数到 N,这server(50,L)条线)没关系,但在较大的数字上,它会崩溃:

Error in process <0.46.0> with exit value: {badarg,[{primes,number,2,[{file,"primes.erl"},{line,31}]}]}

第 31 行是其中server ! hit之一 - 但我不明白为什么它会失败。也许失败的那一行是之后的那一行,number(N,1)但是为什么会失败呢?

编码:

-module(primes).
-compile(export_all).

main() ->
  pg:create(numbers),
  Server_PID = spawn(?MODULE,server,[]),
  register(server,Server_PID),
  ok.

server()     -> server(2,[]).
server(50,L) -> io:format("Primes: ~p~n",[L]);
server(N,L)  ->
  Num_PID = spawn(?MODULE,number,[N]),
  pg:join(numbers,Num_PID),
  pg:send(numbers,tick),
  receive
    hit ->
      flush(),
      server(N+1,L)
  after 100 ->
      server(N+1,[N|L])
  end.

number(N)   -> receive {pg_message,_,_,tick} -> number(N,1) end.
number(N,I) ->
  receive
    {pg_message,_,_,tick} ->
      if
        N =:= I ->
          server ! hit,
          number(N,1);
        true ->
          number(N,I+1)
      end
  end.

flush() ->
  receive _ -> flush()
  after   0 -> ok end.
4

1 回答 1

8

当一个注册的进程死亡时,它注册的名称不再被注册。虽然向一个引用死进程的 pid 发送消息是完全合法的(消息只是消失了),但发送给一个未注册的名称是一个错误,即使该名称曾经被注册过。

在您的代码中,该server进程执行 50 次循环,生成一个新进程并等待hit消息或超时。之后server/2函数结束并且server进程终止。当它死亡时,该名称server不再注册,因此尝试向它发送消息会产生badarg错误。

于 2012-10-02T21:29:16.043 回答