Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 临时gen_服务器进程和更新PID_Multithreading_Erlang_Gen Server - Fatal编程技术网

Multithreading 临时gen_服务器进程和更新PID

Multithreading 临时gen_服务器进程和更新PID,multithreading,erlang,gen-server,Multithreading,Erlang,Gen Server,我目前正在合理地学习Erlang,但有一个关于gen_服务器和主管的问题。如果gen_服务器进程崩溃,并最终由主管重新启动,则它将收到一个新的pid。现在,如果我希望其他进程通过Pid引用该进程,该怎么办?在这些过程中,“更新”Pid有哪些好的惯用方法 作为一些实际应用程序的练习,我正在编写一个锁服务器,其中客户端可以使用任意密钥请求锁。理想情况下,我希望有一个单独的进程来处理特定锁的锁定和释放,其思想是,如果在N个时间量之后没有人请求,我可以使用gen_server中的timeout参数来终止

我目前正在合理地学习Erlang,但有一个关于gen_服务器和主管的问题。如果gen_服务器进程崩溃,并最终由主管重新启动,则它将收到一个新的pid。现在,如果我希望其他进程通过Pid引用该进程,该怎么办?在这些过程中,“更新”Pid有哪些好的惯用方法

作为一些实际应用程序的练习,我正在编写一个锁服务器,其中客户端可以使用任意密钥请求锁。理想情况下,我希望有一个单独的进程来处理特定锁的锁定和释放,其思想是,如果在N个时间量之后没有人请求,我可以使用gen_server中的timeout参数来终止进程,以便只有当前相关的锁会留在内存中。现在,我有一个目录进程,它将锁名称映射到锁进程。当锁进程终止时,它将从目录中删除锁

我关心的是如何处理客户端在锁进程处于终止中间时请求锁的情况。它还没有关闭,所以嗅探pid是否激活将无法工作。锁定进程尚未到达将其从目录中删除的子句

有没有更好的方法来处理这个问题

编辑

目前有两个gen_服务器:“目录”用于维护来自LockName->Lock Process的ETS表,而“锁服务器”则使用start_child动态添加到监控树中。理想情况下,我希望每个锁服务器都能直接处理与客户端的对话,但我担心在进程崩溃的时候(如果不响应消息),获取/释放发出调用或CAST的请求的场景。
从{local}或{global}开始不起作用,因为它们可能有N个数量。

不要通过pid引用gen_服务器进程

您应该通过
genu服务器:call/2
genu服务器:call/3
函数为genu服务器提供API。它们接受
ServerRef
作为第一个参数,可以是
Name |{Name,Node}|{global,GlobalName}| pid()
。因此,您的API将如下所示:


锁(钥匙)->
genu服务器:调用(?MODULE,{lock,Key})。
释放(键)->
genu服务器:调用(?MODULE,{release,Key})。

请注意,此API与gen_服务器定义在同一个模块中,我假设您使用以下方式启动服务器:

gen_服务器:启动链接({local,?MODULE},?MODULE,[],[])

所以,您的API方法可以通过服务器名称而不是pid来查找服务器,这相当于
?模块


有关更多信息,请参见
gen_server

诀窍是命名进程,而不是通过其pid引用它。你通常有3个可行的选择


  • 使用注册名称。这就是andreypopp的建议。您可以通过服务器的注册名称来引用服务器。本地注册的名称必须是原子,这可能会在某种程度上限制您。全局注册的名称没有此限制,您可以注册任何术语

  • 主管知道Pid。问吧。您必须将主管Pid传递给流程

  • 或者,使用gproc应用程序(存在于上)。它允许你创建一个通用的进程注册表——你可以通过ETS来实现,但是偷取好的代码而不是自己实现


如果所有进程都是同一监督树的一部分,则pid可用。所以其中一个人的死意味着其他人的死。因此,Pids回收并不重要。

通过使用“erlang:monitor/demonitor”API,您可以完全避免使用“lock_server”进程

当客户端请求锁时,您将发出锁。。并在客户端上执行erlang:monitor。。这将返回一个监视器引用。。然后可以将此引用与锁一起存储。。这样做的好处是,当客户端死亡时,您的目录服务器将收到通知。。您可以在客户机中实现超时功能

下面是我最近编写的代码片段。。


基本上,table_manager是一个向客户端发出特定表资源锁的进程。。如果客户端死亡,表将返回到池。

“全局注册的名称没有此限制,您可以注册任何术语”不知道这一点,它可能会很有用。如果我们将子项动态添加到监控树中,并在监控树上添加start\u child,如本例所示,该如何处理?注册到本地或全局将所有功能限制为一个进程,对吗?我个人使用gproc,因此我可以在gproc表中注册任何术语。那么,用这个术语来识别过程是很容易的。嗨,这是一个迟来的评论,我希望你会得到通知。如果我使用gproc遵循您的技术,并在一个函数中说,我按一个gen_服务器的名称(如
{bus,BusId}
)对它进行10次调用,这意味着对gproc进行10次调用,10次ETS查找。可以吗?你不觉得开销太大了吗?对我来说,这似乎是一个完美的解决方案,但性能呢?忘了给你贴上@IGIVECRAPANSWERS标签,请看我之前的评论:)这不会限制我只使用一个进程吗?如果我想有多个子进程呢?是的,会的。陛下我以为您正在使用gen_服务器进程作为“目录”进程,该进程负责管理锁处理程序(将其名称映射到处理锁的进程)。在这种情况下,您也不需要通过pid引用任何进程,“目录”进程(即我们的gen_服务器)通过其名称引用,并且锁处理程序访问应该只通过“目录”进程的API(
lock/1
release/1
)进行处理。您是正确的,目录进程实际上是通过这种方式处理的,注册到当地的一家公司。我的目录API按照您的建议进行处理,因为我只需要一个进程。 lock(Key) -> gen_server:call(?MODULE, {lock, Key}). release(Key) -> gen_server:call(?MODULE, {release, Key}). gen_server:start_link({local, ?MODULE}, ?MODULE, [], [])