我正在使用一个正在检查条件变为true的while循环:
while(Game.gameState != Game.CLOSING)
{
if(reconnecting)
{
time = System.currentTimeMillis();
}
else
{
while(time + desiredWait > System.currentTimeMillis())
{
try{Thread.sleep(5);}catch(InterruptedException e){}
}
time += desiredWait;
}
synchronized (Game.gameStateLock)//added to circumvent the problem
{
if(Game.gameState == Game.INPROGRESS)//problematic condition
{
while(true)
{
synchronized (Lockstep.nextTurns)
{
if(!Lockstep.nextTurns.isEmpty() || lockstep.currentTurn == 0)
break;
}
try{Thread.sleep(5);}catch(InterruptedException e){}
time = System.currentTimeMillis();
}
Lockstep.attemptTurn();
}
}
}
循环不间断地运行(如果重新连接为真),因此在每个循环中访问Game.gameState(类型为int)两次。如果现在在第二个线程(例如,通过网络)中更改了gameState,则while循环/ if条件不检测它并继续拒绝执行if块中的代码,即使它应该。添加的synchronized(Game.gameStateLock)解决了这个问题。它也很难调试,导致打印gameState或其他任何东西都会导致问题不存在。我的猜测是I / O中断/休眠线程或导致它写入/读取那么多数据,cpu的缓存被清除,并且从缓存中读取的gameState变量必须从整个时间重新加载RAM。
这可能是原因吗?我假设原始数据类型在处理多个线程时没有那么多问题(除非你检查一个布尔值,然后将其设置为阻止其他线程)。 Java线程中的原始数据类型是否安全? (我甚至无法同步它们,需要一个虚拟对象)
答案 0 :(得分:2)
"线程安全"这不是你正在寻找的术语,这可能就是你为什么挣扎的原因。您的代码在技术上是“线程安全的”,因为多线程导致您不会遇到任何损坏。然而,你所缺少的是与#34;可见性相关的保证"。在您的情况下,无法保证一个线程所做的更改将是"可见"到另一个。有多种方法可以使变化可见。在您的情况下,使gameState
volatile变得足以强制跨线程查看对该值的更改。
答案 1 :(得分:-1)