避免竞争条件

Max*_*Max 2 erlang

以下代码片段由Francesco Cesarini和Erlang编程的Simon Thompson撰写,作为Erlang中可能的竞争条件的一个例子.

start() -> 
  case whereis(db_server) of
    undefined -> 
      Pid = spawn(db_server, init, []), 
      register(db_server, Pid), 
      {ok, Pid};
    Pid when is_pid(Pid) ->
      {error, already_started}
  end.
Run Code Online (Sandbox Code Playgroud)

在没有逐字复制细节的情况下,作者解释说如果两个进程同时执行start(),那么运行"undefined"部分的进程1可能无法完成,因为进程2会导致它被抢占.然后,进程2将运行"未定义"部分以完成.现在,当进程1恢复时,进程2已经注册了db_server,导致其对register()的调用抛出运行时错误.我希望你能理解我的意思,因为我不想翻阅这本书的文字.

我的问题是,当两个进程同时执行start()时,如何编码上述确切的功能以避免潜在的竞争条件?

cth*_*ops 9

通常,这可以通过让生成的进程注册自己的名称,然后向父进程发回一个响应来告诉父进程是否成功.

start() ->
   Pid = spawn(db_server, init, [self()]),
   receive {Pid, StartResult} ->
       StartResult
   end.

init(Parent) ->
    try register(db_server, self()) of
        true ->
            Parent ! {ok, started},
            real_init()
    catch error:_ ->
        Parent ! {error, already_started}
    end.
Run Code Online (Sandbox Code Playgroud)

(可能无法编译或工作.输入此处而不检查.:))

你可以在gen.erl中找到一个精心实现的版本.实际上,在实际代码中,您只需使用OTP行为来重用该版本.