Search code examples
javamultithreadingslicksystem.outkryonet

Java System.out.println() affecting program flow


I am working on a server/client based game using the KryoNet java library as well as slick. When the server class receives a connection from a client, it sends necessary startup information to the client, including what player number it is. One receiving this, the client starts slick and begins operating normally. The code for this is:

    boolean started = false;
    while(!started){
        System.out.println(cs.playerNum);
        if(cs.playerNum != -1){
            cs.startSlick();
            started = true;
        }
    }

The playerNum is set by another thread when the value is received from the server. For a while I could not get this to work (cs.startSlick() was never called), and eventually I got frustrated and began logging playerNum each time the loop ran. By adding System.out.println(cs.playerNum), the code began working, the loop would evaluate properly and slick would be started.

How is it possible that System.out.println does this? I have tried replacing it with other functions, and even other functions which take cs.playerNum as a parameter, but only when I specifically print cs.playerNum can I get the loop to work. If I need to include more source I can, but the issue seems to be directly here since I have tried replacing System.out.println with other functions to no success.


Solution

  • You kind of answered your own question when you said "The playerNum is set by another thread". What you have is a classic race condition. If your code is able to execute quickly enough, then that playerNum will not have been set by the time it is needed. However, if something were to delay or "interrupt" your code, then the other thread will have time to set the playerNum value, and your code will work as you expected.

    A system call to perform IO forcibly suspends a thread while it waits for that IO action to occur. This happens when you call System.out.println which causes your seemingly tight code to pause briefly yielding to the other thread and allowing you to then retrieve the desired value.

    This is a very basic threading problem, and you will run into much more complex threading problems writing threaded code. As such I would definitely suggest you spend some time reading up on threading in general and understanding how synchronized functions work as well as wait() and notify(), as was suggested in the comments.