gpt4 book ai didi

erlang - 解决两个 gen_tcp 之间的死锁

转载 作者:行者123 更新时间:2023-12-04 23:55:44 24 4
gpt4 key购买 nike

在浏览 erlang 应用程序的代码时,我遇到了一个有趣的设计问题。让我描述一下情况,但由于 PIA,我无法发布任何代码,抱歉。

代码结构为 OTP 应用程序,其中两个 gen_server 模块负责分配某种资源。该应用程序完美运行了一段时间,我们并没有遇到大问题。

当第一个 gen_server 需要检查第二个是否有足够的资源时,棘手的部分就开始了。向第二个 gen_server 发出一个 call,它本身调用一个实用程序库(在非常非常特殊的情况下)向第一个 gen_server 发出一个 call

我对 erlang 比较陌生,但我认为这种情况会使两个 gen_server 互相等待。

这可能是一个设计问题,但我只是想知道 OTP 中是否有任何内置的特殊机制可以防止这种“挂起”。

如有任何帮助,我们将不胜感激。

编辑:总结答案:如果您遇到两个 gen_servercall 以循环方式相互调用的情况,您最好在应用程序设计上多花些时间。

感谢您的帮助:)

最佳答案

这称为死锁,可以/应该在设计层面避免。下面是一个可能的解决方法和一些主观观点,希望能帮助您避免犯错。

虽然有多种方法可以解决您的问题,但“等待”正是 call 正在做的事情。

一种可能的解决方法是从 A 内部生成一个调用 B 的进程,但不会阻止 A 处理来自 B 的调用。该进程将直接回复调用者。

在服务器 A 中:

handle_call(do_spaghetti_call, From, State) ->
spawn(fun() -> gen_server:reply(From, call_server_B(more_spaghetti)) end),
{noreply, State};
handle_call(spaghetti_callback, _From, State) ->
{reply, foobar, State}

在服务器 B 中:

handle_call(more_spaghetti, _From, State) ->
{reply, gen_server:call(server_a, spaghetti_callback), State}

对我来说,这是非常复杂且极难推理的。我认为您甚至可以在不冒犯任何人的情况下将其称为意大利面条代码。

另一方面,虽然上述方法可能会解决您的问题,但您应该仔细考虑这样的调用实际上意味着什么。例如,如果服务器 A 多次执行此调用会怎样?如果在任何时候超时会发生什么?您如何配置超时以使它们有意义? (最内层调用的超时时间必须比外层调用短,等等)。

我会改变设计,即使这很痛苦,因为当你允许它存在并解决它时,你的系统就会变得很难推理。恕我直言,复杂性是万恶之源,应不惜一切代价避免。

关于erlang - 解决两个 gen_tcp 之间的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6036969/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com