Wątki, problem z synchronizacją

0

Mam do zrobienia grę w zapałki, w skrócie chodzi o to że gracze na zmianę biorą jakąś liczbę ze stosu. Mam to zrobić na wątkach (każdy gracz to inny wątek). Problem w tym, że nie potrafię operować wątkami tak by jeden gracz czekał na drugiego. Takie musi być wywołanie całości:

public class Matches {
	public static void main(String[] args) {
		Shared t = new Shared(51, 4);
		Player tab[] = {
				new Player("Alice", t),
				new PlayerMan("The Student I", t, PlayerMan.CONSOLE),
				new Player("Mark", t),
				new PlayerMan("The Student II", t, PlayerMan.INPUT_DIALOG) };
		System.out.println("Glowny watek czeka, az ktos wygra...");
		for (int i = 0; i < tab.length; i++)
			tab[i].start();
	}
}

Napisałem takie o to klasy:

class Shared {

	public int ile = 0;
	public int ktory = 0;
	public int ileZapalek;

	public Shared(int ileZapalek, int ile) {
		this.ileZapalek = ileZapalek;
		this.ile = ile;
	}
}
import java.util.Scanner;

import javax.swing.*;

class PlayerMan extends Player {

	public static final int CONSOLE = 0;
	public static final int INPUT_DIALOG = 1;
	private int input;

	public PlayerMan(String player, Shared shared, int input) {
		super(player, shared);
		this.input = input;
	}

	protected int takeMatches(int ileZapalek) {
		int number = 0;
		do {
			if (input == INPUT_DIALOG)
				number = Integer.parseInt(JOptionPane
						.showInputDialog("Ile bierzesz zapalek?"));
			else if (input == CONSOLE) {
				System.out.println("Ile bierzesz zapałek?");
				Scanner scan = new Scanner(System.in);
				number = Integer.parseInt(scan.next());
			}
		} while (!(number >= 0 && number <= 3));
		return number;
	}

	synchronized public void run() {
		super.run();
	}
}
class Player extends Thread {

	String player;
	Shared shared;

	public Player(String player, Shared shared) {
		this.player = player;
		this.shared = shared;
	}

	protected int takeMatches(int ileZapalek) {
		int number = ileZapalek;
		if (shared.ile > 2)
			return 1;
		if (ileZapalek % 4 == 0 || ileZapalek % 4 == 1)
			number = 1;
		else if (ileZapalek % 4 == 2)
			number = 2;
		else
			number = 3;
		return number;
	}

	synchronized public void run() {
		int number = Integer.parseInt(this.getName().substring(7));
		shared.ktory = number;
		while (true) {
			if (shared.ktory == number) {
				System.out.println("na stole jest " + shared.ileZapalek
						+ " zapalek");
				int ileZapalek = shared.ileZapalek > 3 ? takeMatches(shared.ileZapalek)
						: shared.ileZapalek;
				System.out.println(player + " bierze " + ileZapalek);
				shared.ileZapalek -= ileZapalek;
				if (shared.ileZapalek == 0) {
					System.out.println("Wygral: " + player);
					System.exit(0);
				}
				try {
					Thread.sleep((int) (Math.random() * 7000));
				} catch (InterruptedException exc) {
					return;
				}
			}
		}

	}
}

Istotne są jedynie metody run(), reszty można nie czytać :P Jak widać gubię się w tamtym miejscu i nie mam pojęcia jak wyjść z tego. W tej chwili ten kod działa tak, że leci dowolny gracz i nie patrzy na inne, i tak sobie skacze który chce :/

Proszę o jakąkolwiek pomoc, dzięki

0

Ten kawałek wydaje mi się podejrzany:

 
...
shared.ktory = number;
                while (true) {
                        if (shared.ktory == number) {
...

Skoro inne wątki śpią na mniej więcej kilka sekund, to szansa, że nastąpi kolizja jest bardzo mała.
Powinieneś inaczej sprawdzać, czy inny wątek coś robi w shared, np ustawić domyślnie shared.ktory = 0, i potem robić tak:

 
...
                while (true) {
                        if (shared.ktory == 0) {
                                shared.ktory = 1; // blokujesz stos dla siebie
                                ...
                                ... robisz sobie tam coś ...
                                ...
                                shared.ktory = 0; //zwalniasz stosik dla innych wątków
...

A jeżeli chcesz, aby gracze brali zapałki po kolei, to możesz robić tak, że będziesz sobie liczył ilość utworzonych obiektów typu players, każdy nowy gracz będzie dostawał numer +1 większy od ostatniego, będzie sprawdzał, czy shared.ktory = number-1, a następnie koncowo ustawial shared.ktory = number (ewentualnie 0, kiedy ostatni).

Nie wiem czy dobrze zrozumiałem problem, ale tak to widzę ;p

1 użytkowników online, w tym zalogowanych: 0, gości: 1