Erlang:为什么我不能注册self()?

Nei*_*aft 1 erlang

此行失败,但有badarg异常:

register(myproc, self()),
Run Code Online (Sandbox Code Playgroud)

文档说self/0返回一个pid并且register/2需要一个pid.什么给出了什么?

编辑:不,说真的,它还没有注册,它不是​​一个保留的原子,当我从产生它的过程中注册它时它就可以工作.

太奇怪了!好的,我得到了更多的线索.当我将呼叫转移register()到不同的地方时,有时它会工作,有时它会中断.这是我的示例代码.在你叫我疯了之前先跑吧.:-)

-module(pingpong).
-export([start/1,  ping/2, pong/0]).

ping(N, Pong_Pid) ->
    link(Pong_Pid), 
    pingr(N, Pong_Pid).

pingr(0, _) ->
    io:format("Ping exiting~n", []),
    exit(ping);

pingr(N, Pong_Pid) ->
    Pong_Pid ! {ping, self()},
    receive
        pong ->
            io:format("Ping received pong~n", [])
    end,
    pingr(N - 1, Pong_Pid).

pong() ->
    %% This one works.
    %%register(pong, self()),
    process_flag(trap_exit, true), 
    pongr().

pongr() ->
    %% This one fails.
    register(pong, self()),
    receive
        {ping, Ping_PID} ->
            io:format("Pong received ping~n", []),
            Ping_PID ! pong,
            pongr();
        {'EXIT', From, Reason} ->
            io:format("pong exiting, got ~p~n", [{'EXIT', From, Reason}])
    end.

start(Ping_Node) ->
    PongPID = spawn(pingpong, pong, []),
    spawn(Ping_Node, pingpong, ping, [3, PongPID]).
Run Code Online (Sandbox Code Playgroud)

小智 6

myproc已经注册了吗?

第一次调用应该成功,额外的调用将导致badarg异常.

1> register(myproc, self()).
true
2> myproc ! foo.
foo
3> flush().
Shell got foo
ok
4> register(myproc, self()).
** exception error: bad argument
     in function  register/2
        called as register(myproc,<0.30.0>)
Run Code Online (Sandbox Code Playgroud)


knu*_*tin 6

如果该进程已经注册,它将抛出一个badarg.还有一些其他情况会导致这种情况,就像名称已经使用过一样.有关更多信息,请参阅erlang:register/2文档.

编辑

你发布代码来重现你的问题真是太棒了.

因此,您第一次进入pongr/0时将注册self().当您收到消息时,您将处理它并pongr/0再次呼叫.第二次输入pongr/0时尝试注册self(),但由于已经注册,因此失败.

此外,如果您想使用注册大量进程,您应该查看gproc.register/2需要一个原子作为关键,并且存在大约一百万个原子的限制,除非你明确地改变它.请参阅效率指南.gproc也可以运行分布式,因此可以用来代替global模块.