如何解决函数调用之间的竞争条件

时间:2017-08-11 08:01:49

标签: erlang ejabberd erlang-shell ejabberd-module ejabberd-hooks

我使用erlang的Message传递构造构建了一个多人游戏(确切地说是4个玩家)。我在以下链接上跟随tictactoe游戏作为示例,但真正相似的是消息传递构造,如游戏中所示:link

然后我选择在ejabberd多用户聊天室上运行这个游戏,我确实为此写了一个ejabberd钩子。 但是如果你在上面的链接上查看文件tictactoe.erl中的NewGameState,你会发现没有办法检索它 在一个变量中。

所以我使用了mnesia并将每个新生成的游戏状态写入此mnesia表。 现在在我的ejabberd钩子里面我调用我的游戏功能(即每次调用一系列模块 - >“gen_server,game_modules,mnesia_modules”执行) 在游戏函数调用下方的钩子里面我正在从mnesia表中读取游戏状态,如下所示(这里函数myMessage是ejabberd钩子里面的函数):

myMessage({#message = Msg, C2SState})->
    some_other_module:game_func(Args),
    State=mnesia_module:read(key),

    {Msg, C2SState};
myMessage(Acc) ->
    Acc.

现在我的问题是,当执行顺序为

时,读操作会给我一个空表
some_other_module:game_func(Args),
 GameState=mnesia_module:read(key),

当我将这两行之间的延迟插入timer:sleep/1时,如下所示(在使用不同值进行一些试验后,随机选择值200):

some_other_module:game_func(Args),
timer:sleep(200)
 GameState=mnesia_module:read(key),

我得到GameState的正确值,因此建议我在行中读取操作

GameState=mnesia_module:read(key),

在行some_other_module:game_func(Args)(这是一系列模块 - &gt;“gen_server,game_modules,mnesia_modules”)能够执行mnesia模块并将GameState写入mnesia表之前执行/执行。< / p>

如何解决此问题,因为我不想使用timer:sleep/1,因为它不是可靠的解决方案。

任何人都可以建议我在这里工作。我的意思是,任何人都可以建议我通过除mnesia之外的任何其他方式检索钩子内的GameState,所以我根本没有竞争条件。

或者有一些方法可以让ejabberd提供一些我可以在这里使用的功能吗?

提前致谢。

1 个答案:

答案 0 :(得分:5)

分布式节点之间数据的实时一致性是一个难题,您需要根据需要定制解决方案。你没有说你正在使用mnesia进行什么样的交易,所以也许这可以解决你的问题。

但是,这是一个简单的解决方案,可以帮助您思考问题:

首先,让我们调用您的一个节点master。在主节点上,启动处理游戏状态的gen_server。现在,任何想要阅读或编写游戏状态的人都需要将rpc:call/4主节点(除非它们已经存在)放入gen_server:call/2。现在,与游戏状态的所有交互都是同步的。

如果您每秒更新游戏状态不超过几次,此解决方案应该可以很好地为您服务。如果游戏是独立的,那么每个游戏都是不同的gen_server。