竞争状态的例子

问题描述:

在书编程二郎的第13章的结尾:软件的并行世界,我们都获得了一段代码:竞争状态的例子

keep_alive(Name, Fun) -> 
    register(Name, Pid = spawn(Fun)), 
    on_exit(Pid, fun(_Why) -> keep_alive(Name, Fun) end). 

而且书上说:

  • 进程Pid可能在执行on_exit之前死亡。
  • 如果两个程序试图同时评估keep_alive并且使用相同的值Name,则该代码具有可能发生的争用条件

如果两个程序同时调用keep_alive具有相同Name,那么register电话之一,因为名称已被采取,并且调用进程会死会触发badarg例外。

所以,它不是过程on_exit之前Pid死亡被称为,但过程调用on_exit死亡

什么用这个作为一个例子来描述竞争条件,这里的作者的观点?

不,或者可能实际上死亡。

的过程中提到了Pid可能在Fun第一行中的错误,可以尝试获得一些外部资源作为其第一个动作和 失败(锁定的文件,一个不存在的数据库,等等),它可以很快终止非常无循环等

-module(silly). 
-export([do_stuff/0]). 

do_stuff() -> 
    keep_alive(die_bot, fun i_die_fast/0). 

i_die_fast() -> 
    not_ok = io:format("Is this ok?~n"), 
    receive Anything -> 
     ok = io:format("Received: ~tp~n", [Anything]), 
     i_die_fast() 
    end. 

keep_alive(Name, Fun) -> 
    register(Name, Pid = spawn(Fun)), 
    on_exit(Pid, fun(_Why) -> keep_alive(Name, Fun) end). 

如何将上面的代码打出来的? (io:format/1始终返回ok,所以它不会匹配not_ok并在第一行中崩溃。)i_die_fast/0似乎永久递归,但它永远不会那么远,并且可能会在达到on_exit/2之前死亡。 (但它不是保证死之前on_exit/2被称为!欢迎并发。)

关键是你不知道。最接近你可以知道的是使用spawn_link,或者在较少耦合的情况下使用spawn,然后使用monitorspawn_monitor

竞争状态与register是真实的,以及和可能崩溃当前执行的过程 - 所以这是竞争条件。


旁注:

这就是为什么我几乎总是有这样,如果有冲突,它在孩子,而不是调用的情况下炸毁衍生功能寄存器本身(在大多数情况下,有各种各样的原因为什么你可能想以另一种方式做):

% Note, we don't need the PID of `some_helper` because it is named. 
start() -> 
    _ = spawn_link(fun() -> some_helper() end), 
    main_loop(). 

some_helper() -> 
    true = register(helper, self()), 
    helper_loop().