检查并行进程是不是评估相同的功能

Posted

技术标签:

【中文标题】检查并行进程是不是评估相同的功能【英文标题】:Check if parallel processes evaluate same function检查并行进程是否评估相同的功能 【发布时间】:2014-05-14 11:46:41 【问题描述】:

最近几天,我一直在学习 Erlang,使用的是 Joe Armstrong 的经典著作 Programming Erlang。

我正在关注关于并发编程的章节,在章节的最后,有一个小问题需要解决:

编写一个函数 start(AnAtom, Fun) 将 AnAtom 注册为 spawn(Fun)。 确保您的程序在两个并行的情况下正常工作 进程同时评估 start/2。在这种情况下,您必须 保证这些过程中的一个成功而另一个失败。

我解决了这个问题的第一部分,确保每个进程都使用不同的原子生成。

关于第二部分,我被卡住了,因为如果我理解正确,我无法找到一种方法来检查两个并行进程是否同时评估函数 start/2。起初,我想到了一个计数器来检查进程的生成次数,但我无法理解如何执行此检查。我在this thread 中发现了一些有趣的东西(来自 OOP 背景,我考虑过单例模式),但我不确定使用计数器读取和写入文件是否是执行此检查的最佳方式。我认为有一个简单的方法可以做到这一点。

我写的代码如下:

-module(probl).
-export([start/2,stop/1]).

start(Atom,Fun) ->
% check here counter value
case isUniqueProcess(Times) of % here I'm trying to use a counter, but I'm stuck..
    true ->
        Pid = spawn(fun() -> doSomething(Atom,Fun) end), 
        register(Atom,Pid);
    false ->
        io:format("Sorry, no more processes to spawn."),
        void
end.    

stop(Atom) -> 
    case whereis(Atom) of
        undefined -> void;
        Pid -> io:format("Stopped."), Pid ! stop
    end.

isUniqueProcess(Times) -> % here I should increment the counter, but how?
    if
        Times =:= 0 ->
            true;
        Times > 0 ->
            false
    end.

doSomething(Atom,Fun) ->
    receive
        stop -> void
    after 15000 ->
        Fun(),
        doSomething(Atom,Fun)
    end.

对我来说,来自强大的 OOP 背景,转换另一种编程思维并不容易,就像在 Erlang 中发生的那样,也许这就是我遇到困难的原因。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

如果两个或多个进程都尝试以相同的名称注册,那么只有第一个会成功。以下将在他们尝试注册时产生错误。在这种情况下,仅仅让后续进程崩溃还不够吗?为此,必须在启动的进程本身中完成注册。

如果您不想让进程崩溃,您可以将进程包装在一个 catch 中并终止,然后使用 exit(normal) 显式终止它。

【讨论】:

谢谢!昨天我解决了将过程包装在一个catch中的问题,检查了register()的返回值!【参考方案2】:

你可以试试这个代码。

start(Atom, Fun) when is_atom(Atom), is_function(Fun, 0) ->
    Sender = self(),
    Fun2 = fun() ->
           case catch register(Atom, self()) of
               true ->
               Sender ! started, self(),
               Fun();
               _ ->
               Sender ! already_running, self()
           end
       end,
    Pid = spawn(Fun2),
    receive
    started, Pid ->
        ok, Pid;
    already_running, Pid ->
        already_running
    end.

【讨论】:

感谢您的回答。我试过你的代码,但我注意到start 函数的性能不是很好,因为有一条消息传递给检查。我将尝试以更简单的方式解决问题。感谢您的建议!【参考方案3】:

使用rvirding 方法:

start(AnAtom, Fun) ->
  spawn(fun() -> register(AnAtom, self()), Fun() end).

或者:

start(AnAtom, Fun) ->
  spawn(fun() -> case catch register(AnAtom, self()) of true -> Fun(); _ -> ok end end).

【讨论】:

感谢您的回答!我解决了将过程包装在一个catch中的问题,检查了register()的返回值!

以上是关于检查并行进程是不是评估相同的功能的主要内容,如果未能解决你的问题,请参考以下文章

Haskell 中的并行“任何”或“全部”

并发编程之多进程

多处理时正确检查文件是不是存在

如何检查子进程是不是正确终止? [复制]

Julia:即使被要求运行多个进程,spawnat 也始终在相同的线程上运行

从 Skopt 中的检查点恢复 gp_minimize 进程