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

Erlang 检查并行进程是否评估相同的功能,erlang,Erlang,几天以来,我一直在学习Erlang,使用乔·阿姆斯特朗(Joe Armstrong)的名著 我将遵循关于并发编程的一章,在这一章的末尾,有一个小问题需要解决: 编写一个函数start(AnAtom,Fun)将AnAtom注册为spawn(Fun)。 确保程序在两个并行的情况下正常工作 过程同时评估start/2。在这种情况下,您必须 确保其中一个进程成功,另一个进程失败 我解决了这个问题的第一部分,确保每个进程将产生一个不同的原子 关于第二部分,我被卡住了,因为如果我理解正确,我无法找到一种方法

几天以来,我一直在学习Erlang,使用乔·阿姆斯特朗(Joe Armstrong)的名著

我将遵循关于并发编程的一章,在这一章的末尾,有一个小问题需要解决:

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

我解决了这个问题的第一部分,确保每个进程将产生一个不同的原子

关于第二部分,我被卡住了,因为如果我理解正确,我无法找到一种方法来检查两个并行进程是否同时计算函数
start/2
。起初,我考虑使用计数器来检查进程的繁殖数量,但我不知道如何执行此检查。我在这里发现了一些有趣的东西(来自OOP背景,我考虑了Singleton模式),但我不确定读写带有计数器的文件是否是执行此检查的最佳方式。我认为有一个简单的方法可以做到这一点

我写的代码如下:

-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.
对我来说,来自强大的面向对象编程背景,转换另一种编程思维方式并不容易,就像在Erlang中发生的那样,这可能是我遇到困难的原因。如何解决此问题?

您可以尝试此代码

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(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.

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


如果不想使进程崩溃,可以将进程包装在catch中,然后使用
exit(normal)

终止并显式终止它。如果两个或多个进程都尝试以相同的名称注册,则只有第一个进程会成功。以下内容将在他们尝试注册时生成错误。在这种情况下,仅仅让后续流程崩溃还不够吗?要做到这一点,注册必须在启动的进程本身中完成

如果您不想使进程崩溃,您可以将进程包装在catch中,然后使用
exit(normal)

方法终止并显式终止它:

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).
使用方法:

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).

谢谢你的回答。我尝试了你的代码,但是我注意到
start
函数的性能不是很好,因为有一条消息传递给检查。我会试着用一种更简单的方法来解决这个问题。谢谢你的建议!谢谢你的回答。我尝试了你的代码,但是我注意到
start
函数的性能不是很好,因为有一条消息传递给检查。我会试着用一种更简单的方法来解决这个问题。谢谢你的建议!非常感谢。昨天我解决了在catch中包装进程的问题,检查
register()的返回值
!非常感谢。昨天我解决了在catch中包装进程的问题,检查
register()的返回值
!谢谢你的回答!我解决了在catch中包装进程的问题,检查
register()的返回值
!谢谢你的回答!我解决了在catch中包装进程的问题,检查
register()的返回值