concurrency - Erlang - 餐饮哲学家的错误

标签 concurrency erlang

很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。如需帮助澄清这个问题以便重新打开它,visit the help center .




9年前关闭。




如果代码难以遵循,我深表歉意。
这是经典的哲学家就餐问题,有 5 位哲学家在吃饭,但只有 5 根棍子——你需要两根才能吃。

这些是说明,如果有人感兴趣:
http://www.kth.se/polopoly_fs/1.260940!/Menu/general/column-content/attachment/philosophers.pdf

无论如何,这里是代码,筷子过程代码:

-module(chopstick).
-export([start/0]).

start() ->
spawn_link(fun() -> init() end).
init() ->
available().

available() ->
receive
    {request, From} -> 
        From ! granted,
        gone();
    quit ->
        ok
        end.
gone() ->
receive
    returned ->
        available();
    quit ->
        ok
        end.

哲学家进程代码:
-module(eater).
-import(timer, [sleep/1]).
-import(random, [uniform/1]).
-export([start/5, dream/5, eat/5, wait/5]).

start(Hungry, Right, Left, Name, Ctrl) ->
dream(Hungry, Right, Left, Name, Ctrl).

 **%This was wrong, it should say start(Hungry, Right, Left, Name, Ctrl) ->
 spawn_link(fun() -> dream(Hungry, Right, Left, Name, Ctrl) end).**

dream(Hungry, Right, Left, Name, Ctrl) -> 
Time = 500+uniform:random(500),   **%This was wrong, it should say random:uniform**
timer:sleep(Time),
Right! {request, self()},
Left! {request, self()},
%skicka {request, self()} till två pinnar
wait(Hungry, Right, Left, Name, Ctrl).

wait(Hungry, Right, Left, Name, Ctrl) ->
receive
    granted ->  
        io:format("~s received a chopstick~n", [Name]),
        receive
            granted ->
            io:format("~s received a chopstick~n", [Name]),
            io:format("~s started eating~n", [Name]),
            eat(Hungry, Right, Left, Name, Ctrl)
            end;
    _ -> wait(Hungry, Right, Left, Name, Ctrl)
end.

eat(Hungry, Right, Left, Name, Ctrl) ->
Time = 500+uniform:random(500), **%This was wrong, it should say random:uniform**
timer:sleep(Time),
Right! returned,
Left! returned,
io:format("~s put back two chopsticks~n", [Name]),
if 
    Hungry =< 1 ->
        Ctrl ! done;
    true ->
        dream(Hungry-1, Right, Left, Name, Ctrl)
end.    

最后是宿主进程:
-module(dinner).
-export([start/0]).


start() ->
spawn(fun() -> init() end).

init() ->
C1 = chopstick:start(),
C2 = chopstick:start(),
C3 = chopstick:start(),
C4 = chopstick:start(),
C5 = chopstick:start(),
Ctrl = self(),
eater:start(5, C1, C2, "Confucios", Ctrl),  **% This is where it crashes**
eater:start(5, C2, C3, "Avicenna", Ctrl),
eater:start(5, C3, C4, "Plato", Ctrl),
eater:start(5, C4, C5, "Kant", Ctrl),
eater:start(5, C5, C1, "Descartes", Ctrl),
wait(5, [C1, C2, C3, C4, C5]).


wait(0, Chopsticks) ->
lists:foreach(fun(C) -> C ! quit end, Chopsticks);
wait(N, Chopsticks) ->
receive
    done ->
        wait(N-1, Chopsticks);
    abort ->
        erlang:exit(abort)
end.

输出:
11> dinner:start().
<0.85.0>
12> 
=ERROR REPORT==== 10-Nov-2011::02:19:10 ===
 Error in process <0.85.0> with exit value: {undef,[{uniform,random,[500]}, {eater,dream,5},{dinner,init,0}]}

非常感谢您阅读所有这些内容,我还没有学会如何阅读 erlang 的错误报告。如果可以,并且想告诉我这意味着什么,请这样做。

最佳答案

我认为问题在于你有三个模块:dinner , eater , 和 chopstick ,但尝试调用philospher:start在您的 dinner:init/0功能。试试 eater:start反而。

第二个问题是生成随机数时模块和函数名的顺序;替换 uniform:randomrandom:uniform在您的 eater.erl :

1> dinner:start().
<0.35.0>
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Confucios received a chopstick
Confucios received a chopstick
Confucios started eating
Confucios put back two chopsticks
Avicenna received a chopstick
Avicenna received a chopstick
Avicenna started eating
...

这很快就显示了第三个问题——我们应该从第一个错误报告中发现——吃者实际上并不在他们自己的进程中。所以编辑eater.erl使start()函数读取:
start(Hungry, Right, Left, Name, Ctrl) ->
    spawn_link(fun() -> dream(Hungry, Right, Left, Name, Ctrl) end).

现在它按预期工作:
1> dinner:start().
<0.35.0>
Confucios received a chopstick
Plato received a chopstick
Confucios received a chopstick
Confucios started eating
Descartes received a chopstick
Kant received a chopstick
Confucios put back two chopsticks
Avicenna received a chopstick
...

谢谢。这很有趣。

关于concurrency - Erlang - 餐饮哲学家的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8073878/

相关文章:

erlang - 从 erlang 插入 cassandra

node.js - erlang 将 http 查询绑定(bind)到 ip(或接口(interface))

c# - 如何创建无重复的ConcurrentQueue?

Ruby 和 JRuby 在同一台 Windows 7 计算机上

concurrency - 如何在 Rust 中使用锁?

concurrency - clojure pmap/preduce vs fork-join

erlang - 在erlang中比较宏中的两个字符串时程序出错

erlang - 使用 "+native"编译的约束/限制是什么?

c++ - 是否有任何不是用 Java 编写的 Serious Graph 数据库?

java - 与 Java 或其他非函数式语言相比,Scala 究竟如何利用更多的核心?