[Java] Di cosa soffre questo programma ?
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:
e l'output è questo (che chiaramente varia di volta in volta)
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
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
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.
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
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