Почему второй вызов для получения не получает сообщение в оболочке Erlang? - PullRequest
2 голосов
/ 25 февраля 2020

Я играю с процессами в Erlang и пытаюсь создать простой счетчик процессов. Он получает PID отправителя, увеличивает внутренний счетчик и отправляет новое значение счетчика отправителю. Я запускаю свой код из оболочки erl (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

Вот как это выглядит в моей консоли. enter image description here

1 Ответ

3 голосов
/ 25 февраля 2020

Первый прием связывает переменную V с 1, поэтому второй прием становится:

receive 
    1 -> ...

end

И, поскольку сообщение 1 никогда не приходит, время второго приема истекает. После истечения времени ожидания вы можете позвонить flush() в оболочке, и вы увидите, что в почтовом ящике было сообщение 2. Вы также можете вызвать b() в любое время, чтобы отобразить текущие переменные и их значения (которые называются связываниями) - попробуйте это после выполнения первого приема.

В вашей функции вы также выполняете рекурсивное получение в пределах получения в получении, так что первое получение никогда не заканчивается. Чтобы доказать это, вы можете поместить оператор печати после:

Receiver(New)

, например:

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

, и вы никогда не увидите вывод. Вы должны изменить свой прием на что-то вроде этого:

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).
...