【发布时间】:2012-04-24 07:24:43
【问题描述】:
我正在考虑如何将“蚂蚁农场模拟器”移植到 Erlang。这是基本的纲要:
1) 定义一个 100x100 的“插槽”世界
2) 蚂蚁占据一个槽
3) 蚁群占据位置 50,50
4) 食物在地图周围随机放置
5) 蚂蚁一次移动一格寻找食物并将其带回蚁群
6) 一次只能在一个槽中放置一个对象。
这个问题的目标是让系统尽可能地并发。在 Clojure 中,上述问题通过拥有一个代理线程池来解决,每个代理为单个蚂蚁运行 AI。然后这些蚂蚁通过事务更新全局状态。
这是我一直在思考的全球状态。我们如何去构建“游戏世界”?
我的第一个想法是为每个蚂蚁创建一个 Erlang 进程,然后为 map 中的每个插槽创建一个进程。为了移动,蚂蚁会做以下事情:
1) 蚂蚁告诉它当前的槽“我想向北移动”
2) 插槽向北调用插槽并说“请更新您的内容以现在包含蚂蚁“pid””
3) 如果北槽已经有蚂蚁,它会发送一个“拒绝”响应,该响应会向下渗透到包含蚂蚁的槽(然后是蚂蚁)。如果更新有效,则“授权”被发送到链下,蚂蚁更新其内部状态。
我唯一不喜欢这种方法的是,在移动过程中,蚂蚁、它的槽和目标槽都被“锁定”,直到整个事务完成。然后,这会为死锁打开自己的大门。也就是说,两只蚂蚁可能同时试图交换位置,每个位置都在等待另一个位置。
谁能提出更好的解决方案?
---编辑----
让我一步步解决死锁问题:
1) Ant 1 请求 slot A“向北转移”到 slot 2 2) Ant 2 要求 slot B “向南转移”到 slot 1 3)slot 1向slot 2发送传输请求,等待回复 4) slot 2 向 slot 1 发送传输请求,等待回复
从代码的角度来看,这很容易实现,但也会出现死锁,因为每个插槽只监听来自另一个插槽的回复。我想“正确的方法”可能是在转移过程中自动拒绝所有转移请求。
【问题讨论】:
-
我喜欢你的方法的一般声音,并同意你想避免致命的拥抱。也许你可以通过添加蚂蚁不能交换位置的规则来解决你的致命拥抱。相反,他们必须互相绕行,或者至少有一个绕行。也就是说,需要一只蚂蚁去邻近的空地。
-
为什么请求必须是同步和阻塞的?您可以发送请求,然后坐下来等待消息,包括其他请求和您的请求的答案。
标签: concurrency erlang