【问题标题】:How to pass-by-reference a List of Tuples to multiple threads in Erlang?如何通过引用将元组列表传递给 Erlang 中的多个线程?
【发布时间】:2019-06-17 17:25:13
【问题描述】:

我正在构建一个客户端/银行 erlang 项目,我希望将一个元组列表传递给各个线程(ProcessID),​​以便每当一个线程更改列表中的某些值时,其他线程/进程也可以在同一个副本上工作名单。

这是必需的,因为我希望客户线程进行一些计算并从银行扣除余额。 到目前为止,我能够为所有银行和客户创建一个流程,并且客户能够调用银行流程并扣款,但这种扣款只发生在客户流程拥有的银行列表副本中。 我怎样才能拥有元组列表的通用/全局副本或按引用传递的副本,以便它可以由不同的进程相互处理。

Pid = spawn(customer, bazCust, [Name, Loan]),
T = {Name, Pid, Loan},
Pid ! {self(), Name, Loan, Pid, BankPidList},
get_feedback(),

我在上面使用的 BankPidList 如下所示:

[{rbc,<0.2067.0>,800},{bmo,<0.2068.0>,700},{ing,<0.2069.0>,200},0]

我对 Erlang 很陌生(才 4 天),所以可能有一些艺术我没有非常有效地使用,但我现在只需要在不考虑效率的情况下完成功能。

【问题讨论】:

  • 你见过ETS(Erlang Term Storage)吗? Erlang 中没有全局变量。我认为您必须使用 ETS 表。
  • 还没了解。如果 ETS 表可以解决我的问题,我会看看这个。

标签: erlang


【解决方案1】:

致最近被问题淹没的所有银行/客户:

  1. 在 erlang 中,术语 thread 不存在。他们被称为processes。底层实现无关紧要。请不要在任何关于 erlang 的帖子中再次说 thread

  2. 你的老师很烂。如果您真的想学习 erlang,请购买 Programming Erlang,阅读并完成所有练习。

我正在构建一个客户/银行 erlang 项目,我希望传递一个列表 元组到各种线程(ProcessIDs),这样每当一个线程 更改列表中的某些值,其他线程/进程也可以使用 列表的相同副本。

您已经介绍过 OTP gen_servers 了吗? gen_server 建立了客户端-服务器关系,客户端可以向 gen_server 询问列表的当前值。客户端还可以更改列表的值。 gen_server 进入一个递归循环,像这样:

loop(State) ->
    receive
        {get_state} -> 
            %send State to client
            loop(State);
        {set_state, 10} ->  
            loop([10|NewState])
    end
end

当你启动 gen_server 时,State 可以是一个列表,例如[],或[1, 2, 3]。客户端可以向服务器发送消息以获取 State 变量的值或设置 State 变量。

我对 Erlang 很陌生(仅 4 天)

那么您将无法编写程序:您所能做的就是请其他人为您编写代码。那有什么好处?为什么你的老师认为学了 4 天的 erlang 就可以写一个多进程程序了?

到目前为止,我已经能够为所有银行和客户创建一个流程,并且 客户可以致电银行流程并扣款,但 这种扣除只发生在银行名单的副本中 客户流程有。我怎样才能拥有通用/全局副本或 元组列表的传递引用副本,因此它可以相互 由不同的流程处理。

erlang(以及所有其他函数式语言)的主要原则是没有进程可以更改另一个进程正在处理的数据。您所能做的就是将数据副本发送到另一个进程。如果银行流程需要知道客户账户中有多少钱,那么它可以在递归循环中跟踪余额:

init(Deposit) ->
    loop(Deposit).

loop(Balance) ->
    receive
        {From, {deduct, Amount}} ->
            case Balance >= Amount of
               true -> 
                   From ! whatever,
                   bank(Balance - Amount);

               _    -> 
                   From ! whatever
                   bank(Balance)
            end
    end.

您还可以在接收子句中添加deposit 消息:

    {From, {deposit, Amount}} ->
        From ! whatever,
        bank(Balance + Amount)

Balance 也可以是一个元组列表,其中每个元组是一个客户帐户,具有更合适的变量名称,例如 Balances。要在Balances 列表中查找客户,您可以使用lists:keyfind();删除旧余额可以使用lists:keydelete(),添加新余额可以使用:[{Pid, NewBalance} | Balances]

【讨论】:

  • 感谢您对 gen_server 的详细回答和建议。可能需要使用它来完成我的项目。我还需要列表:用于添加和删除的函数。一旦我能够做到这一点,将更新帖子。
【解决方案2】:

语言并没有变得太复杂,我通过构建一个银行模块并将其流程 ID 传递给所有其他客户来完成我的项目。客户对此 processId 进行更改(通过发送消息/邮件通过

PID!{IDENTIFIER,{parameters}}

而不是对其自己的本地副本进行更改。 您可以通过使用模块名称(或某些特定名称)注册 processIds 来使您的工作更轻松

register(Name, Pid)

但是对于像我这样的初学者,重新运行模块时会出现很多错误(不知道为什么,但解决方案是终止进程并重新编译)。同样,我是 Erlang 的初学者,可能会错过正确的特定语言术语。 以下是我的代码的链接 https://github.com/NitinNanda/Scalable-Message-Passing-Bank-Client.git

【讨论】:

    猜你喜欢
    • 2020-05-03
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 2018-06-29
    • 2013-12-19
    相关资源
    最近更新 更多