为什么第二次调用receive没有在Erlangshell中检索到消息?

yzuktlbb  于 2022-12-16  发布在  Erlang
关注(0)|答案(1)|浏览(222)

我正在用Erlang处理进程,并尝试创建一个简单的计数器进程。它接收发送方的PID,递增内部计数器,并将新的计数器值发送给发送方。我正在从erlshell(Erlang/OTP 20,Eshell V9.2)启动代码。我能够成功地从计数器进程接收第一个回复,但不能接收第二个。

%% Process function that serves as a counter
CounterFun = fun() ->
  (fun Receiver(Current) ->
    io:format("  -- Entering receiver, current ~p~n", [Current]),
    receive
      Sender ->
        New = Current + 1,
        io:format("  -- Sending ~p to ~p~n", [New, Sender]),
        Sender ! New,
        Receiver(New)
    end
  end)(0)
end.

CounterPid = spawn(CounterFun).

CounterPid ! self().
receive V -> V after 3000 -> timeout end. % Will provide 1

CounterPid ! self().
receive V -> V after 3000 -> timeout end. % Will result in timeout

这是它在我的控制台中的样子。x1c 0d1x

zsbz8rwp

zsbz8rwp1#

第一次接收将变量V绑定到1,因此第二次接收变为:

receive 
    1 -> ...

end

而且,由于消息1从未到达,第二次接收超时。超时后,您可以在shell中调用flush(),您将看到邮箱中有一条消息2。您还可以随时调用b()以显示当前变量及其值(称为绑定)--在执行第一次接收后尝试这样做。
在你的函数中,你也在一个receive中的一个receive中进行递归receive,这样第一个receive就永远不会结束。为了证明这一点,你可以在后面放一个print语句:

Receiver(New)

例如:

io:format("receive ending with Current= ~w~n", [Current])

你将永远看不到任何输出。你应该把你的receive改成这样:

New = Currrent + 1
receive
  Sender ->
    io:format("  -- Sending ~p to ~p~n", [New, Sender]),
    Sender ! New,
    io:format("receive ending with Current= ~w~n", [Current])
end,
counter(New).

相关问题