【问题标题】:What happens when a gen_server method gets called simultaneously by two clients?当 gen_server 方法被两个客户端同时调用时会发生什么?
【发布时间】:2012-05-31 12:28:40
【问题描述】:

我有一个 gen_server 模块,它在客户端进程发送数据时将数据记录到文件中。当两个客户端进程同时向这个模块发送数据时会发生什么?文件操作会不会相互冲突? erlang documentation 在这里令人沮丧地不清楚。

【问题讨论】:

    标签: erlang gen-server


    【解决方案1】:

    gen_server 在与您的客户端进程不同的进程中运行,因此当您对其执行 call/cast 时,您实际上是在向服务器进程发送消息。

    所有消息都放在一个进程的消息队列中,并且进程一个接一个地处理它们的消息。如果消息在进程繁忙时到达,则将其放入消息队列中。因此,同时到达的日志消息不会相互干扰,因为它们将按顺序处理。

    这不是 gen_server 本身的属性,而是 erlang 中所有进程的一般属性,这就是为什么在 gen_server 文档中没有提及这一点的原因。

    【讨论】:

      【解决方案2】:

      幸运的是,OTP 的源代码在 github 上很容易获得,但简短的回答是 gen_server 在循环中运行,按接收到的顺序回答请求,没有一种类型(handle_cast、handle_call 或 handle_info)的优先级高于另一个。

      使用 handle_call 可能会成为一个问题,因为 gen_server 进程必须先返回,然后才能处理队列中的下一个 cast/call/info。例如,在 handle_call 中,避免使用 self() 调用 gen_server:call!

      【讨论】:

        【解决方案3】:

        每个 Erlang 进程都维护一个消息队列。该过程将获取一条消息并一一处理这些消息。

        在你的例子中,如果两个客户端同时调用gen_server,这些调用将成为gen_server进程队列中的一条消息,gen_server会一一处理这些消息。所以不必担心冲突。

        但如果一个进程要处理来自其他进程的消息过多,则需要考虑进程的容量并优化设计,否则会成为瓶颈。

        【讨论】:

        • 谢谢!我设法找到了问题。事实证明,这根本不是并发问题(正如您所指出的),而是序列化问题。我没有正确使用 Erlang 位串语法来序列化我的数据,因此字节丢失了。
        【解决方案4】:

        gen_server 只是按照完成的顺序处理请求,不管它们是从一个进程还是多个进程完成的。

        在写入日志的情况下,没有理由担心竞争条件。

        【讨论】:

          猜你喜欢
          • 2014-03-18
          • 2013-02-03
          • 2018-08-17
          • 2021-09-14
          • 2022-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-25
          相关资源
          最近更新 更多