gpt4 book ai didi

java - 十字路口的线程同步

转载 作者:行者123 更新时间:2023-12-03 11:00:43 25 4
gpt4 key购买 nike

所以,我有这个项目,即将到期,恐怕我不太了解线程同步的概念。实际上,我似乎根本无法理解,所以如果我的问题很愚蠢 - 我提前道歉。

这个想法很简单——我有多个线程代表动物(羚羊、狮子等。扩展 Animal 实现 Runnable),以及一个 2D 数组的 Tile 对象。动物需要在没有碰撞的情况下移动 - 如果一个动物想移动到另一个站立的方 block ,它应该与它交互(),然后 - 如果另一个没有死 - 等它离开。

所以,当一只动物移动时,它显然需要在目标瓦片上同步,这样两只动物就不能同时进入一个瓦片。然而,当它移动时,它显然需要在它站立的瓷砖上调用 notify(),以便其他想要移动到那里的动物可以醒来。

我尝试锁定两者,但结果是动物无缘无故地停在了它们的轨道上。这里有一段代码,稍微澄清一下:

void move(dir direction)
{
Integer tarX = ((direction==dir.east?(x+1):(direction==dir.west?(x-1):x))); // east->x+1/west->x-1/NS->x
Integer tarY = ((direction==dir.north?(y-1):(direction==dir.south?(y+1):y))); //see above
Animal an;
synchronized(TileManager.getInstance().playField[tarX][tarY])
{

an = AnimalManager.getInstance().searchByXY(tarX, tarY);
while (an != null)
{
interact(an); //assume it's empty - if it isn't, it results in a death of target animal anyway
an = AnimalManager.getInstance().searchByXY(tarX, tarY); //possibly redundant?
if (an != null) {
try {
TileManager.getInstance().playField[tarX][tarY].wait();
} catch (InterruptedException ex) {
}
}
an = AnimalManager.getInstance().searchByXY(tarX, tarY, dir.none);
}
synchronized(TileManager.getInstance().playField[x][y])
{
int prevX = x;
int prevY = y;
x = tarX;
y = tarY;
TileManager.getInstance().playField[prevX][prevY].notify();
TileManager.getInstance().playField[x][y].notify();
}
}
}

是的,这是一团糟,我知道,而且效果也不是很好。有人知道该怎么做吗?

最佳答案

您必须查看此解决方案的性能是否正常,但您可以引入某种必须锁定的“Arbiter”对象,以便同步访问任何 PlayField。

模式将是:

private static final Object arbiter = new Object( );

void move(dir direction)
{
...
TileManager tileManager = TileManager.getInstance( );

synchronized( arbiter )
{
PlayField tarXtarYField = tileManager.playField[tarX][tarY];

synchronized( tarXtarYField )
{
...

PlayField xyField = tileManager.playField[x][y];
synchronized( xyField )
{
...
tileManager.playField[prevX][prevY].notify();
xyField.notify();
}
}
}
}

此模式将帮助您避免死锁,但代价是游戏移动速度较慢,因为对游戏区域的访问本质上是通过 arbiter 对象序列化的,因此一次只能移动 1 个线程.

如果 field 不是太大,动物数量少,表现还可以。如果不是,那么您真的必须从头开始重写这个程序。

关于java - 十字路口的线程同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14062948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com