I'm using a while loop that is checking for a condition to become true:
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();
}
}
}
The loop runs uninterrupted without sleeping (if reconnecting is true), and therefore accesses Game.gameState (of type int) two times in each cycle. If gameState is now changed in a second thread (e.g. via network), the while loop/if condition doesn't detect it and continues refusing to execute the code in the if block even if it should. The added synchronized(Game.gameStateLock) solves this problem. It is also really hard to debug, cause printing the gameState or anything else will cause the problem to be nonexistent. My guess is that I/O interrupts/sleeps the thread or causes it to write/read that much data, that the cache of the cpu is cleared and the gameState variable which has been read from cache the whole time has to be reloaded from the RAM.
Can this be the reason? I assumed primitive data types to be not that much of a problem when dealing with multiple threads (unless you're checking a boolean and then setting it to block other threads). Are primitive data types in Java thread safe? (i can't even synchronize on them, needed a dummy object)