1

I have a problem with a simple program that simulate a Roulette Game with N random player. The program work 2-3 time than stop accidentally because, i think, a thread remain in wait or anything like that. I know that the code isn't so good (like my English) but is my first attempt. Any suggestion are really appreciated. Sorry if the code isn't really clean, i don't really find other ways to do this program.

public class RouletteMultipla implements Runnable {
private int a;
private int ng; //number of player

public RouletteMultipla(int f) {
    ng = f;
}

int numero = 0;

public void ingioco() {
    a++; //How many player have put money
}

public void morto() {
    System.out.println("One player is died"); //Run out of Money
    ng--;
}

public void run() {
    while (true) {
        synchronized (this) {
            if (a == ng) { //until all player have put money
                numero = (new Numero().num); //Random from 0 to 36
                System.out.println("E' USCITO " + numero + "\n ");
                a = 0;
                for (double j = 0; j < 10000000; j = j + 0.1);
                notifyAll();
            }

        }

    }

}

public static void main(String[] args) {
    int ng = (int) (Math.random() * 14) + 1;
    RouletteMultipla r = new RouletteMultipla(ng);
    Thread roulette = new Thread(r);


    for (int i = 0; i < ng; i++) {
        Giocatore g = new Giocatore(i, r, ng); //create n player
        g.start();

    }
    roulette.start(); //create one roulette
    roulette.setPriority(10);

}

This is class Player

public class Giocatore extends Thread {

private int id; //id of player
private int ng; //number of player

int soldi = 100; //money at start
int numero; //number
int puntata = 1; //roulette play at start

Giocatore(int i, RouletteMultipla s, int b) {
    id = i;
    r = s;
    ng = b;
}

RouletteMultipla r = new RouletteMultipla(ng);

public void run() {

    while (soldi > 0) {
        numero = ((int) (Math.random() * 35)) + 1;
        puntata = (int) (Math.random() * (soldi - 1)) + 1;
        soldi = soldi - puntata;
        System.out.println("ID:" + id + " Puntata:" + puntata + " Numero:" + numero + " SOLDI:" + soldi);

        r.ingioco(); //Increase "a variable"
        try {
            synchronized (r) {
                r.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (numero == r.numero) {
            soldi = soldi + puntata * 36;
            System.out.println("Giocatore " + id + " HA VINTOOOOOOOOOO");
        }

    }
    r.morto(); // when money=0
}

}

1 Answers1

1

There may be other issues, but one that stands out to me is that access to the ng variable is not synchronised nor atomic:

public void morto() {
    System.out.println("One player is died"); //Run out of Money
    ng--;
}

If multiple (player) threads call this method simultaneously, there is no guarantee that ng-- actually causes ng to contain the correct number of players.

The easiest way to understand the problem is probably to think of n--; as being the same as n = n - 1;. Now if two threads simultaneously run this, they may both read n as the same value (eg 10), and both store the same decremented result back (eg 9). Despite two threads having finished, the count is one higher than it should be.

You should probably declare the method as synchronized. I think there is a similar issue with the ingioco method.

davmac
  • 20,150
  • 1
  • 40
  • 68