【发布时间】:2021-06-11 02:54:39
【问题描述】:
我正在编写一个使用 KryoNet 程序生成的宇宙的视频游戏。
有点上下文,KryoNet 将序列化对象,然后对象中的每个引用连同它并尝试将其发送到连接的另一端,如果它找到无法序列化的东西,它会抛出一个错误。
现在我正在尝试游戏的多人游戏部分,我遇到了竞争条件的问题,其中一个线程通过将对象添加到具有引用的集合来进行修改,例如它添加了一个具有引用的对象当我压缩对象并通过网络发送它之间的一个线程,因此它序列化整个对象图,当它应该在接收到对象后在客户端上找到相应的ID时,找到具有我得到的ID的对象服务器,并在到达连接的另一端时重构引用。
例子:
public class Fleet()
{
...
List shipList;
...
public void SendToClient()
{
for (Ship ship : shipList)
{
this.DoNotModify = true;
ship.compress(); //Function that removes all class references from it and assigns an object specific ID
for (int i=0;i<MultiplayerController.clients.size();i++)
clients.get(i).connection.sendTCP(object);
ship.decompress(); //Reassign class references from ID's by looking them up from a HashMap
this.DoNotModify = false;
}
}
public void AddShip(Ship ship)
{
if (!this.DoNotModify)
{
...
//execute time expensive code
...
shipList.add(ship);
}
}
}
这是伪代码,但最终发生在它调用 ship.compress() 和 connection.SendTCP() 之间,它在另一个线程上调用 shipList.add(),该线程添加了一个类似对整个引用的船行星,并且该行星具有对其他军队的引用,依此类推,它会发送整个对象图。或者,它会遍历对象图并尝试发送一个不会序列化的对象,但它只会因 KryoNetException 而爆炸。
所以我试图弄清楚该怎么做,但由于我无法添加一个标志来检查它是否在一些玩家进入游戏后不可避免地在两个方法调用之间被修改它只是炸了,还没有找到解决办法。可能有一些简单的方法可以修复这种竞争条件,但是使用“同步”关键字在这里不起作用,因为它们是单独的方法调用。在这里创建我自己的锁也不起作用,因为它同时在不同的线程上运行这两个函数,并且在检查了布尔值之后它通过函数运行,尝试删除引用,然后尝试序列化一堆它不应该的东西.
我什至考虑过创建一种队列,只要线程在 Thread.Sleep() 或其他东西上,它就会序列化事物,但这将是我不想创建的一个彻头彻尾的痛苦一个完整的子系统。
想法?我在这里不知所措。如果有一个简单的解决方法,请告诉我,我全神贯注。
【问题讨论】:
标签: java multithreading multiplayer kryo kryonet