erlang 为什么simple_one_for_one工作进程可以共享相同的子规格标识?

mqkwyuun  于 2022-12-08  发布在  Erlang
关注(0)|答案(2)|浏览(179)

我为一个名为band_supervisor的主管定义了simple_one_for_one工作者规范,子规范id为jam_musician

init([]) ->
    {ok, {{simple_one_for_one, 3, 60},
    [{jam_musician,
    {musicians, start_link, []},
    temporary, 1000, worker, [musicians]}
    ]}};

音乐家模块是:

-module(musicians).
-behaviour(gen_server).

-export([start_link/2, stop/1]).
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, code_change/3, terminate/2]).

-record(state, {name="", role, skill=good}).
-define(DELAY, 750).

start_link(Role, Skill) ->
  gen_server:start_link({local, Role}, ?MODULE, [Role, Skill], []).

stop(Role) -> gen_server:call(Role, stop).

我可以通过以下方式创建许多工作线程:

3> supervisor:start_child(band_supervisor, [drum, good]).
Musician Arnold Ramon, playing the drum entered the room
{ok,<0.696.0>}
3> supervisor:start_child(band_supervisor, [guitar, good]).
Musician Wanda Perlstein, playing the guitar entered the room
{ok,<0.698.0>}

我注意到所有员工都具有相同的子规范ID:jam_musician
你知道其他类型的工人必须有唯一的孩子id,对吗?

mpgws1up

mpgws1up1#

最有可能的情况是,您将子进程(我假设它是一个gen_server)的start_link函数编写为:

start_link() ->
    gen_server:start_link({local,Name}, ?MODULE, [], []).

这不仅调用init/1函数,还使用atom Name注册进程。
因此,在第二个时刻启动的任何新子节点都将尝试使用第一个子节点已经使用的名称在Erlang节点中注册。
为了避免这种名称冲突,您应该使用类似以下的内容:

start_link() ->
    gen_server:start_link(?MODULE, [], []).

这样就没有孩子会有一个注册的名字,你就不会有冲突。
如果您确实需要注册每个子进程,则可以使用gproc

0yg35tkg

0yg35tkg2#

The child specification identifier will be the same for simple_one_for_one supervisors since there is only one child type and many child instances (workers) of this type.
From the supervisor behaviour docs :
Notice that when the restart strategy is simple_one_for_one , the list of child specifications must be a list with one child specification only. (The child specification identifier is ignored.) No child process is then started during the initialization phase, but all children are assumed to be started dynamically using start_child/2 .

相关问题