当前位置: 首页 > 知识库问答 >
问题:

(我的实现)进程不通信

皇甫通
2023-03-14

我正试图为著名的Dijkstra餐厅哲学家问题实现我自己的解决方案。我得到的只是状态机,一个哲学家应该同时抓住这两个叉子。

这是我的代码:

-module(assess3).
-compile([export_all]).

-define(EAT,1000).
-define(THINK,1000).

college() ->
    R = spawn_link(?MODULE, report,[]),

    F1 = spawn_link(?MODULE, fork,["fork1",R]),
    F2 = spawn_link(?MODULE, fork,["fork2",R]),
    F3 = spawn_link(?MODULE, fork,["fork3",R]),
    F4 = spawn_link(?MODULE, fork,["fork4",R]),
    F5 = spawn_link(?MODULE, fork,["fork5",R]),

    spawn_link(?MODULE, philosopher,["Socrates", R, F1,F2]),
    spawn_link(?MODULE, philosopher,["Confucius", R, F2,F3]),
    spawn_link(?MODULE, philosopher,["Aristole", R, F3,F4]),
    spawn_link(?MODULE, philosopher,["Homer", R, F4,F5]),
    spawn_link(?MODULE, sphilosopher,["Plato", R, F1,F5]).

%%create philosophers randomly
philosopher(Name, Report, LeftF, RightF) ->
    random:seed(erlang:phash2([node()]),
                erlang:monotonic_time(),erlang:unique_integer()),
    create_phils(Name,Report,LeftF,RightF).

%%create special philosopher
sphilosopher(Name, Report, RightF, LeftF) ->
    random:seed(erlang:phash2([node()]),
                erlang:monotonic_time(),erlang:unique_integer()),
    create_special_phil(Name,Report,RightF,LeftF).

%%creates random 4 philosophers who get the Left fork first then the right fork
create_phils(Name,Report,LeftF,RightF) ->
    %%thinking state
    reporting(Name,Report,thinking),
    timer:sleep(random:uniform(?THINK)),
    %%hungry state
    reporting(Name,Report,hungry),
    LeftF ! RightF! {pick,self()},
    receive
        {pick, LeftF} -> reporting(Report, Name, left);
        {pick, RightF} -> reporting(Report, Name, right)
    end,
    receive
        {pick, LeftF} -> reporting(Report, Name, left);
        {pick, RightF} -> reporting(Report, Name, right)
    end,
    %%eating state
    reporting(Report,Name,eating),
    timer:sleep(random:uniform(?EAT)),
    LeftF ! RightF ! {let_go,self()},
    create_phils(Name,Report,LeftF,RightF).

%%create special philosopher who attempts to communicate first with the
%%right fork proccess instead of the left fork
create_special_phil(Name,Report,RightF,LeftF) ->
    %%thinking state
    reporting(Name,Report,thinking),
    timer:sleep(random:uniform(?THINK)),
    %%hungry state
    reporting(Name,Report,hungry),
    RightF ! LeftF ! {pick,self()},
    receive
        {pick, RightF} -> reporting(Report, Name, right);
        {pick, LeftF} -> reporting(Report, Name, left)
    end,
    receive
        {pick, RightF} -> reporting(Report, Name, right);
        {pick, LeftF} -> reporting(Report, Name, left)
    end,
    %%eating state
    reporting(Report,Name,eating),
    timer:sleep(random:uniform(?EAT)),
    RightF ! LeftF ! {let_go,self()},
    create_special_phil(Name,Report,RightF,LeftF).

%%prepares what the Report proccess will print
reporting(Name,Report,Status) ->
    Report ! {Name,Status,self()},
    receive
        {Report,ack} -> true
    end.

%%Report proccess, receives and prints
report() ->
    receive
        {Name,Status, Pid} ->
            io:format("~s : ~s ~n",[Name,status(Status)]),
            Pid ! {ack,self()},
            report()
    end.

%%function to pass the appropriate status in string for io:format
status(Status) ->
    case Status of
        thinking ->  "is thinking";
        hungry -> "is hungry";
        eating -> "is eating";
        right -> "got right fork";
        left -> "got left fork";
        on_table -> "on table";
        in_use ->"in use";
        Status -> atom_to_list(Status)
    end.

fork(Name,Report) ->
    receive
        {picked,Pid} ->
            reporting(Report,Name,in_use),
            Pid ! {picked,self()},

            receive
                {let_go,Pid} ->
                    reporting(Report,Name,on_table)
            end,
            fork(Name,Report)
    end.

除了尝试运行assess3:college()时,我没有收到任何错误在Erlang shell中,我看到的不是进程通信,而是:

苏格拉底是思考吗?孔子是思考吗

我不明白为什么会发生这种情况,因为在我开始编码之前,为了避免迷路,我手工设计了一切。任何帮助赞赏。

这个实现应该是为了防止死锁,因为四个哲学家首先抓住左边的叉子,第五个哲学家则试图首先抓住右边的叉子,尽管我知道这可能会导致资源匮乏,这意味着一个哲学家可能永远不会吃东西。我现在不在乎这个,一步一个脚印。

共有1个答案

徐卓
2023-03-14

您有几个与不匹配的消息和顺序错误的函数参数相关的问题。不匹配的消息会导致东西永远挂起等待从未发送的消息。由于错误的参数问题,修复这些问题会导致崩溃。

例如,考虑您的代码> For < /Cult>函数:

fork(Name,Report) ->
    receive
        {picked,Pid} ->
            reporting(Report,Name,in_use),
            Pid ! {picked,self()},

            receive
                {let_go,Pid} ->
                    reporting(Report,Name,on_table)
            end,
            fork(Name,Report)
    end.

它在等待一个{选择的,...}消息,但是你的哲学家正在发送{选择,...}消息,它用一个{选择的,...}消息回复,但是哲学家希望收到{选择,...}消息。

查看您的报告功能:

report() ->
    receive
        {Name,Status, Pid} ->
            io:format("~s : ~s ~n",[Name,status(Status)]),
            Pid ! {ack,self()},
            report()
    end.

它将{ack,self()}消息发送回Pid,但这些进程需要{Report,ack}消息。

在许多您称之为报告(报告、名称等)的地方 其中报告名称参数顺序错误。

这里有一个固定的版本,似乎工作。

-module(assess3).
-compile([export_all]).

-define(EAT,1000).
-define(THINK,1000).

college() ->
    R = spawn_link(?MODULE, report,[]),

    F1 = spawn_link(?MODULE, fork,["fork1",R]),
    F2 = spawn_link(?MODULE, fork,["fork2",R]),
    F3 = spawn_link(?MODULE, fork,["fork3",R]),
    F4 = spawn_link(?MODULE, fork,["fork4",R]),
    F5 = spawn_link(?MODULE, fork,["fork5",R]),

    spawn_link(?MODULE, philosopher,["Socrates", R, F1,F2]),
    spawn_link(?MODULE, philosopher,["Confucius", R, F2,F3]),
    spawn_link(?MODULE, philosopher,["Aristole", R, F3,F4]),
    spawn_link(?MODULE, philosopher,["Homer", R, F4,F5]),
    spawn_link(?MODULE, sphilosopher,["Plato", R, F1,F5]).

%%create philosophers randomly
philosopher(Name, Report, LeftF, RightF) ->
    random:seed(erlang:phash2([node()]),
                erlang:monotonic_time(),erlang:unique_integer()),
    create_phils(Name,Report,LeftF,RightF).

%%create special philosopher
sphilosopher(Name, Report, RightF, LeftF) ->
    random:seed(erlang:phash2([node()]),
                erlang:monotonic_time(),erlang:unique_integer()),
    create_special_phil(Name,Report,RightF,LeftF).

%%creates random 4 philosophers who get the Left fork first then the right fork
create_phils(Name,Report,LeftF,RightF) ->
    %%thinking state
    reporting(Name,Report,thinking),
    timer:sleep(random:uniform(?THINK)),
    %%hungry state
    reporting(Name,Report,hungry),
    LeftF ! RightF ! {pick,self()},
    receive
        {picked, LeftF} -> reporting(Name, Report, left);
        {picked, RightF} -> reporting(Name, Report, right)
    end,
    receive
        {picked, LeftF} -> reporting(Name, Report, left);
        {picked, RightF} -> reporting(Name, Report, right)
    end,
    %%eating state
    reporting(Name,Report,eating),
    timer:sleep(random:uniform(?EAT)),
    LeftF ! RightF ! {let_go,self()},
    create_phils(Name,Report,LeftF,RightF).

%%create special philosopher who attempts to communicate first with the
%%right fork proccess instead of the left fork
create_special_phil(Name,Report,RightF,LeftF) ->
    %%thinking state
    reporting(Name,Report,thinking),
    timer:sleep(random:uniform(?THINK)),
    %%hungry state
    reporting(Name,Report,hungry),
    RightF ! LeftF ! {pick,self()},
    receive
        {picked, RightF} -> reporting(Name, Report, right);
        {picked, LeftF} -> reporting(Name, Report, left)
    end,
    receive
        {picked, RightF} -> reporting(Name, Report, right);
        {picked, LeftF} -> reporting(Name, Report, left)
    end,
    %%eating state
    reporting(Name,Report,eating),
    timer:sleep(random:uniform(?EAT)),
    RightF ! LeftF ! {let_go,self()},
    create_special_phil(Name,Report,RightF,LeftF).

%%prepares what the Report proccess will print
reporting(Name,Report,Status) ->
    Report ! {Name,Status,self()},
    receive
        {Report,ack} -> ok
    end.

%%Report proccess, receives and prints
report() ->
    receive
        {Name,Status,Pid} ->
            io:format("~s : ~s ~n",[Name,status(Status)]),
            Pid ! {self(),ack},
            report()
    end.

%%function to pass the appropriate status in string for io:format
status(Status) ->
    case Status of
        thinking ->  "is thinking";
        hungry -> "is hungry";
        eating -> "is eating";
        right -> "got right fork";
        left -> "got left fork";
        on_table -> "on table";
        in_use ->"in use";
        Status -> atom_to_list(Status)
    end.

fork(Name,Report) ->
    receive
        {pick,Pid} ->
            reporting(Name,Report,in_use),
            Pid ! {picked,self()},

            receive
                {let_go,Pid} ->
                    reporting(Name,Report,on_table)
            end,
            fork(Name,Report)
    end.
 类似资料:
  • 本文向大家介绍Linux 进程通信之FIFO的实现,包括了Linux 进程通信之FIFO的实现的使用技巧和注意事项,需要的朋友参考一下 FIFO通信(first in first out) FIFO 有名管道,实现无血缘关系进程通信。 创建一个管道的伪文件 a.mkfifo testfifo 命令创建 b.也可以使用函数int mkfifo(const char *pathname, mode_t

  • 本文向大家介绍c# 如何实现不同进程之间的通信,包括了c# 如何实现不同进程之间的通信的使用技巧和注意事项,需要的朋友参考一下   进程之间的通信是为了解决不同进程之间的数据传输问题,这样可以让不同程序交互数据。实现进程通信的方式:1、剪切板;2、COM;3、内存映射文件;4、WCF 1、剪切板Clipboard在进程间传送对象   剪切板是一个供应用程序使用的公有区域。在.NET中定一个了一个D

  • 本文向大家介绍WinForm实现跨进程通信的方法,包括了WinForm实现跨进程通信的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例展示了WinForm实现跨进程通信的方法,分享给大家供大家参考之用。具体方法如下: 主要功能代码如下: 希望本文所述实例对大家C#程序设计有所帮助。

  • 本文向大家介绍python执行子进程实现进程间通信的方法,包括了python执行子进程实现进程间通信的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python执行子进程实现进程间通信的方法。分享给大家供大家参考。具体实现方法如下: a.py: b.py: 希望本文所述对大家的Python程序设计有所帮助。

  • 本文向大家介绍Python通过队列来实现进程间通信的示例,包括了Python通过队列来实现进程间通信的示例的使用技巧和注意事项,需要的朋友参考一下 Python程序中,在进程和进程之间是不共享全局变量的数据的。 我们来看一个例子: 进程 p1 里对全局变量 nums 循环进行处理,进程 p2 将 nums 打印出来,发现 nums 的值没有变化。 运行结果: in process1 pid=578

  • 本文向大家介绍Android通过继承Binder类实现多进程通信,包括了Android通过继承Binder类实现多进程通信的使用技巧和注意事项,需要的朋友参考一下 AIDL的底层是通过Binder进行通信的,通过追踪.aidl编译后自动生成的文件我们知道,文件中的Stub类用于服务端,Proxy类用于客户端调用,那么可否直接通过继承Binder类实现多进程通信呢?下面就来试一试。 效果图: 服务端