【发布时间】:2012-05-31 12:28:40
【问题描述】:
我有一个 gen_server 模块,它在客户端进程发送数据时将数据记录到文件中。当两个客户端进程同时向这个模块发送数据时会发生什么?文件操作会不会相互冲突? erlang documentation 在这里令人沮丧地不清楚。
【问题讨论】:
标签: erlang gen-server
我有一个 gen_server 模块,它在客户端进程发送数据时将数据记录到文件中。当两个客户端进程同时向这个模块发送数据时会发生什么?文件操作会不会相互冲突? erlang documentation 在这里令人沮丧地不清楚。
【问题讨论】:
标签: erlang gen-server
gen_server 在与您的客户端进程不同的进程中运行,因此当您对其执行 call/cast 时,您实际上是在向服务器进程发送消息。
所有消息都放在一个进程的消息队列中,并且进程一个接一个地处理它们的消息。如果消息在进程繁忙时到达,则将其放入消息队列中。因此,同时到达的日志消息不会相互干扰,因为它们将按顺序处理。
这不是 gen_server 本身的属性,而是 erlang 中所有进程的一般属性,这就是为什么在 gen_server 文档中没有提及这一点的原因。
【讨论】:
幸运的是,OTP 的源代码在 github 上很容易获得,但简短的回答是 gen_server 在循环中运行,按接收到的顺序回答请求,没有一种类型(handle_cast、handle_call 或 handle_info)的优先级高于另一个。
使用 handle_call 可能会成为一个问题,因为 gen_server 进程必须先返回,然后才能处理队列中的下一个 cast/call/info。例如,在 handle_call 中,避免使用 self() 调用 gen_server:call!
【讨论】:
每个 Erlang 进程都维护一个消息队列。该过程将获取一条消息并一一处理这些消息。
在你的例子中,如果两个客户端同时调用gen_server,这些调用将成为gen_server进程队列中的一条消息,gen_server会一一处理这些消息。所以不必担心冲突。
但如果一个进程要处理来自其他进程的消息过多,则需要考虑进程的容量并优化设计,否则会成为瓶颈。
【讨论】:
gen_server 只是按照完成的顺序处理请求,不管它们是从一个进程还是多个进程完成的。
在写入日志的情况下,没有理由担心竞争条件。
【讨论】: