DEV Community

Discussion on: Multithreading in Java for dummies (part 2)

Collapse
 
daniftodi profile image
Dan • Edited

It's a great tutorial, thank you.

I observed a problem, sometimes multi player game stuck, in my case I used 6 players and every time stuck after player4. Give me please some ticks about how to debug it ?

public void run() {
        while(!Thread.interrupted()) {
            lock.lock();
            System.out.println(text + " lock");
            try {
                System.out.println(text + " mustplay");
                while (!mustPlay)
                    myTurn.awaitUninterruptibly();

                System.out.println(text);
                this.mustPlay = false;
                nextPlayer.mustPlay = true;
                nextTurn.signal();
                System.out.println(text + " signal");
            } finally {
                System.out.println(text + " unlock");
                lock.unlock();
            }
        }
    }

Enter fullscreen mode Exit fullscreen mode

Output:

player0 lock
player0 mustplay
player0
player0 signal
player0 unlock
player1
player1 signal
player1 unlock
player1 lock
player1 mustplay
player2
player2 signal
player2 unlock
player2 lock
player2 mustplay
player3
player3 signal
player3 unlock
player4
player4 signal
player4 unlock
player4 lock
player4 mustplay
player3 lock
player3 mustplay
player5
player5 signal
player5 unlock
player5 lock
player5 mustplay
player0 lock
player0 mustplay
player0
player0 signal
player0 unlock
player1
player1 signal
player1 unlock
player1 lock
player1 mustplay
player2
player2 signal
player2 unlock
player2 lock
player2 mustplay
player3
player3 signal
player3 unlock
player4
player4 signal
player4 unlock
player4 lock
player4 mustplay
player5
player5 signal
player5 unlock
Enter fullscreen mode Exit fullscreen mode
Collapse
 
raulavila profile image
Raúl Ávila • Edited

Thanks for your message, you have discovered a bug in my implementation, which reveals how hard it is to work with concurrent systems.

The problem is in myTurn.awaitUninterruptibly(), as its name expresses, this method is not interruptible, so when the main class interrupts all the threads, if one of the threads is blocked due to the call to this awaitUninterruptibly method, then the thread won't wake up. This situation is not extremely likely, in fact it didn't happen to me when I implemented the example, but I was able to reproduce it after reading your message.

Debugging this kind of issues is quite hard, and it took me some time to understand what was going on. The only solution that comes to my mind at the moment is changing the call to awaitUninterruptibly to await, which receives a timeout. We can configure a long timeout if we want, but for this case 1 minute is more than enough, in fact the timeout will never happen, as the method will be interrupted:

     while(!Thread.interrupted()) {
            lock.lock();

            try {
                while (!play)
                    myTurn.await(1, TimeUnit.MINUTES);

                this.play = false;
                nextPlayer.play = true;

                nextTurn.signal();

            } catch(InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            finally {
                lock.unlock();
            }
        }
Enter fullscreen mode Exit fullscreen mode

Note that we need to catch InterruptedException and propagate the interruption to the thread, so the loop exits normally.

I hope it makes sense, and again, thanks for your message!!!