[Java] Di cosa soffre questo programma ?

giogiomogio
Salve a tutti ho da risolvere questo esercizio:
Prendete il codice sorgente ‘S2Esercizio4.java’ e analizzatelo nel dettaglio. Individuate e descrivete il
problema di esecuzione concorrente di cui soffre e correggetelo. Per la risoluzione, utilizzate gli arrays
atomici di Java. Descrivete la soluzione da voi sviluppata.

l'esercizio in questione è questo:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

final class S2E4Timer {
	private long start = -1, stop = -1;

	public final void start() {
		start = System.currentTimeMillis();
	}

	public final void stop() {
		stop = System.currentTimeMillis();
	}

	public final long getElapsed() {
		if (start < 0 || stop < 0)
			return 0;
		return stop - start;
	}
}

class ModifyWorker implements Runnable {
	private int cnt;

	public ModifyWorker(final int cnt) {
		this.cnt = cnt;
	}

	@Override
	public void run() {
		final ThreadLocalRandom localRandom = ThreadLocalRandom.current();

		for (int i = 0; i < 300; i++) {
			final String string;
			cnt++;
			if (cnt >= 3)
				cnt = 0;
			if (cnt == 0)
				string = S2Esercizio4.s1;
			else if (cnt == 1)
				string = S2Esercizio4.s2;
			else
				string = S2Esercizio4.s3;

			final int position = localRandom.nextInt(0,
					S2Esercizio4.SHARED_LIST_SIZE);
			S2Esercizio4.sharedArray[position] = string;

			try {
				Thread.sleep(localRandom.nextLong(5, 11));
			} catch (final InterruptedException e) {
				/* do nothing */
			}
		}
	}
}

class ReadWorker implements Runnable {
	private final int id;
	private final String stringToSearch;
	private long matchCounter;

	public ReadWorker(final int id, final String stringToSearch) {
		this.id = id;
		this.stringToSearch = stringToSearch;
		this.matchCounter = 0;
	}

	@Override
	public void run() {
		for (int i = 0; i < 300; i++) {
			for (int j = 0; j < S2Esercizio4.SHARED_LIST_SIZE; j++) {
				if (S2Esercizio4.sharedArray[j].equals(stringToSearch))
					matchCounter++;
			}
		}
		log("finished");
	}

	public final void logChangesCount() {
		log("string '" + stringToSearch + "' found  " + matchCounter + " times");
	}

	private final void log(final String msg) {
		System.out.println(getClass().getSimpleName() + id + ": " + msg);
	}
}

public class S2Esercizio4 {
	private static final int NUM_MODIFY_WORKERS = 15;
	private static final int NUM_READ_WORKERS = 5;

	public static final int SHARED_LIST_SIZE = 500000;
	public static final String s1 = new String("Bim");
	public static final String s2 = new String("Bum");
	public static final String s3 = new String("Bam");

	static final String[] sharedArray = new String[SHARED_LIST_SIZE];

	public static void main(final String[] args) {

		final S2E4Timer mainTimer = new S2E4Timer();

		for (int i = 0; i < SHARED_LIST_SIZE; i++) {
			final int tmp = i % 3;
			if (tmp == 0)
				sharedArray[i] = s1;
			else if (tmp == 2)
				sharedArray[i] = s2;
			else
				sharedArray[i] = s3;
		}

		final List<Thread> allThreads = new ArrayList<Thread>();
		for (int i = 0; i < NUM_MODIFY_WORKERS; i++)
			allThreads.add(new Thread(new ModifyWorker(i)));
		final List<ReadWorker> allReadWorkers = new ArrayList<ReadWorker>();
		for (int i = 0; i < NUM_READ_WORKERS; i++) {
			final int tmp = i % 3;
			final ReadWorker worker;
			if (tmp == 0)
				worker = new ReadWorker(i, s1);
			else if (tmp == 2)
				worker = new ReadWorker(i, s2);
			else
				worker = new ReadWorker(i, s3);
			allReadWorkers.add(worker);
			allThreads.add(new Thread(worker));
		}

		System.out.println("Simulation started");
		System.out.println("---------------------------");
		mainTimer.start();
		for (final Thread t : allThreads)
			t.start();

		for (final Thread t : allThreads)
			try {
				t.join();
			} catch (final InterruptedException e) {
				/* do nothing */
			}
		mainTimer.stop();
		System.out.println("---------------------------");
		System.out.println("Simulation finished");
		for (final ReadWorker worker : allReadWorkers)
			worker.logChangesCount();
		System.out.println("Simulation took: " + mainTimer.getElapsed());
	}
}

e l'output è questo (che chiaramente varia di volta in volta)
Simulation started
---------------------------
ReadWorker0: finished
ReadWorker1: finished
ReadWorker4: finished
ReadWorker3: finished
ReadWorker2: finished
---------------------------
Simulation finished
ReadWorker0: string 'Bim' found  6628 times
ReadWorker1: string 'Bam' found  3993 times
ReadWorker2: string 'Bum' found  5187 times
ReadWorker3: string 'Bim' found  5717 times
ReadWorker4: string 'Bam' found  3997 times
Simulation took: 2542


Il codice l'ho analizzato ma (a me pare) che è un esercizio così demenziale che non riesco a capire che cosa ci si aspetti come output... nel senso: cosa vuoi come output per dire "ok, ora mi da un output corretto?".

E' chiaro che ci sono problemi di visibilità e di atomicità ... ma se non si capisce che cosa debba fare (nella maniera corretta) questo programma... è chiaro che non so cosa correggere.

Quindi provo a chiedere a voi se la pensate come me... (che è un esercizio privo di senso) e, in caso, cosa dovrebbe fare o meglio qual'è il senso da attribuire ad un programma del genere.

Qual'è un esempio di output corretto?

Grazie

Risposte
apatriarca
In effetti non è chiaro che cosa stia effettivamente cercando di fare. Ad una rapida occhiata sembrerebbe che il codice crei un certo numero di thread, una parte dei quali modifica l'array condiviso e il resto legge da esso. Non è però del tutto chiaro quale sia lo scopo.

giogiomogio
Infatti, anche perche nel mentre che i threads leggono dall array condivisa ce un thread che si occupa di modificarne i suoi valori...
quindi ogni thread legge valori diversi.
Cio comporta ad avere una sequenza del tutto randomica.
Impossibile quindi capire cosa ci si aspetti...

Bho... io penso che sia un problema di visibilità e di atomicità.
si usa un ReferenceArray cosi da poter avere garanzie sulla visibilità e atomicità...
ma per il resto impossibile capire cosa si vuole

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.