竞争状态的例子
问题描述:
在书编程二郎的第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
,然后使用monitor
或spawn_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().