Dictionary Elixir中的HashDict和OTP GenServer上下文

Dictionary Elixir中的HashDict和OTP GenServer上下文,dictionary,elixir,otp,gen-server,Dictionary,Elixir,Otp,Gen Server,我在OTP中使用HashDict函数时遇到问题。我想使用一个GenServer进程来put,另一个进程来fetch。当我尝试实现这一点时,当从同一个GenServer调用时,我可以从HashDict放置和获取项目;它工作得非常完美(在下面的示例中为MyServerA)。但是,当我使用一个GenServer来put和另一个fetch时,fetch实现不起作用。为什么会这样?大概是因为我需要在三个不同的进程之间传递HashDict数据结构 代码示例如下: 我使用一个简单的调用将一些状态发送到MySe

我在OTP中使用HashDict
函数时遇到问题。我想使用一个
GenServer
进程来
put
,另一个进程来
fetch
。当我尝试实现这一点时,当从同一个GenServer调用时,我可以从
HashDict
放置和获取项目;它工作得非常完美(在下面的示例中为MyServerA
)。但是,当我使用一个
GenServer
put
和另一个
fetch
时,fetch实现不起作用。为什么会这样?大概是因为我需要在三个不同的进程之间传递
HashDict
数据结构

代码示例如下:

我使用一个简单的调用将一些状态发送到
MyServerB

myserver.add\u更新(状态)
对于
MyServerB
,我实现了
HashDict
,如下所示:

defmodule MyServerB do
使用GenServer
def启动链接do
GenServer.start_链接(_模块,[],名称:_模块)
结束
def init([])do
#初始化HashDict以存储状态
d=HashDict.new
{:好的,d}
结束
#客户端API
def添加_更新(更新)do
GenServer.cast\uuuuu模块{:添加,更新}
结束
def get_状态(窗口)do
GenServer.call _模块_,{:get,key}
结束
#服务器API
def handle_cast({:add,update},dict)do
%{key:key}=update
dict=HashDict.put(dict,key,some_值)
{:noreply,dict}
结束
def handle_调用({:get,some_key},_from,dict)do
value=HashDict.fetch!(迪克特,一些钥匙)
{:reply,value,dict}
结束
结束
因此,如果从另一个进程使用MyServerB.get_state(dict,some_key),我似乎无法返回HashDict的内容

更新:

因此,如果我使用ETS,我有如下内容:

def init do
ets=:ets.new(:my_table,[:ordered_set,:named_table])
{:好的,ets}
结束
def handle_cast({:add,update},state)do
update=:ets.insert(:my_table,{key,value})
{:诺雷普利,ups}
结束
def handle_调用({:get,some_key},_from,state)do
sum=:ets.foldl(fn({key},{value},acc)
当key==some_key->value+acc时
(u,acc)->
行政协调会
结束,0,:my_表)
{:答复、总数、状态}
结束
因此,
cast
再次起作用-当我使用
observer
进行检查时,我可以看到它充满了我的键值对。但是,当我尝试调用
时,它再次不返回任何结果。所以我想知道我是否在错误地处理状态??感谢您的帮助


谢谢

您的问题在于此声明:

我想使用一个GenServer进程进行put,使用另一个进程进行fetch

在长生不老药中,进程不能共享状态。因此,不能让一个进程处理数据,而让另一个进程直接读取数据。例如,您可以将HashDict存储在一个进程中,然后让另一个进程向第一个进程发送一条请求数据的消息。这将使它看起来像您描述的那样,但是在幕后,它仍然会让所有事务通过第一个流程。有一些技术可以以分布式/并发的方式来实现这一点,这样就可以利用多个内核,但这可能比您目前要做的工作还要多


看看ETS,它将允许您创建一个公共表并从多个进程访问数据。

ETS是一个不错的选择。无法在genserver之间共享HashDict作为状态

我真的不知道您是如何测试代码的,但ETS在默认情况下将读写并发性设置为false。例如,如果并行读写没有问题,则可以将init函数更改为:

def init do
  ets = :ets.new :my_table, [:ordered_set, :named_table,
                             read_concurrency: true,
                             write_concurrency: true]
  {:ok, ets}
end

希望这能有所帮助。

谢谢。所以我尝试了你的建议,我(天真地理解)也遇到了类似的问题。我编辑了原始问题…这产生了不同:-)但是,我现在得到以下错误:`引发了异常:**(ArgumentError)参数错误:ets.safe_fixtable(true,true)`-我怀疑这是因为我同时执行
插入
foldl
?从erlang文档来看,似乎有一个修复ETS表的设置,但我不确定如何做,或者这是否是问题的根本原因?是的,你是对的。您是否正在使用枚举.foldl/3
?ETS有自己的
foldl
功能。从文档中可以看出:“如果函数将对象插入到表中,或者另一个进程将对象插入到表中,那么这些对象(取决于键顺序)可能会包括在遍历中。”我相信,如果使用该函数,在插入时应该不会有任何问题。如果你真的想同时使用
List.foldl/3
或删除记录,你应该看看这篇文章[。它解释了如何使用
safe\u fixtable
。我正在使用
:ets.foldl
-我现在已经让它工作了,谢谢你的帮助!