ForkJoin modello

di il
1 risposte

ForkJoin modello

A breve avrò un esonero di programmazione multicore.
Mi sono imbattuto in queste domande:

In riferimento al modello di programmazione ForkJoin con thread espliciti, discutete brevemente
il modello di memoria, illustrando:
• l’accessibilità di diverse zone di memoria da parte di thread diversi;
• la modalità con cui il programmatore può condividere informazioni tra thread diversi.


So che ogni thread in (credo) qualsiasi OS, ha un proprio PC che mantiene traccia dell'istruzione che si sta eseguendo, di un proprio stack delle chiamate, dove ogni stack frame mantiene le variabili locali delle funzioni in esecuzione ancora non terminate, dei campi statici che sono visibili a tutti gli altri thread, e mantiene gli oggetti istanziati nell'heap. Nell'heap tutti gli oggetti sono condivisi quindi è possibile condividere informazioni sia utilizzando riferimenti da diversi thread allo stesso oggetto, o utilizzando campi statici.

Però ad esempio:

class SumThread extends java.lang.Thread{
   int lo, hi, and=0;
   int[] arr;
   
   SumThread(int[] arr, int lo, int hi){this.arr = arr; this.lo = lo; this.hi = hi;}
   
   public void run(){
      SumThread lett = new SumThread(arr,lo,(hi+lo)/2);
      SumThread right = new SumThread(arr,(hi+lo)/2,hi);
      
      left.start();
      right.start();
      left.join();
      right,join();
      
      and = left.ans + right.ans; 
   }
}
In questo caso i thread figli, comunicano al thread padre chiamante il proprio risultato tramite un campo public.

Avete consigli? Qualcosa da aggiungere?

Grazie e buon weekend

1 Risposte

  • Re: ForkJoin modello

    Paolovox ha scritto:


    So che ogni thread in (credo) qualsiasi OS, ha un proprio PC che mantiene traccia dell'istruzione che si sta eseguendo, di un proprio stack delle chiamate, dove ogni stack frame mantiene le variabili locali delle funzioni in esecuzione ancora non terminate, dei campi statici che sono visibili a tutti gli altri thread, e mantiene gli oggetti istanziati nell'heap. Nell'heap tutti gli oggetti sono condivisi quindi è possibile condividere informazioni sia utilizzando riferimenti da diversi thread allo stesso oggetto, o utilizzando campi statici.
    Quello che non hai colto è un'altra cosa, più importante. Il Java Memory Model dice chiaramente che il compilatore (il Just-In-Time compiler in modo specifico, si intende) ma anche il processore fisico possono applicare ottimizzazioni e riordinamenti del codice, tali per cui all'interno di un singolo flusso di esecuzione non diano problemi fintanto che il risultato finale sia lo stesso che ci sarebbe senza tutte queste ottimizzazioni e riordinamenti. Se la semantica di un singolo flusso di esecuzione non cambia, compilatore/processore possono fare tutti i "giochi" che vogliono sui dati e sul codice.

    Ma quando ci sono più thread le cose cambiano, queste ottimizzazioni e riordinamenti possono creare situazioni "paradossali" e portare a scenari in cui ciò che un thread si aspetta da un altro thread non è più così ovvio e scontato.

    Andando al succo: senza preoccuparsi di mettere in atto meccanismi appositi di sincronizzazione, semplicemente NON è affatto garantito che ciò che fa un thread in memoria sia "visibile" ad un altro thread.

    Usare la parola chiave volatile su una variabile condivisa garantisce la "visibilità" delle modifiche ma non la mutua-esclusione, quindi non evita una race-condition. Per avere la mutua-esclusione bisogna mettere in atto una apposita sincronizzazione, sfruttanto metodi/blocchi synchronized o con altri meccanismi di sincronizzazione di alto livello offerti dal framework.

    Esistono però dei punti di sincronizzazione impliciti, ben definiti dal Java Memory Model e riguardano anche l'avvio/terminazione di un thread.

    Dato un t1.start(), è GARANTITO che tutto quello fatto prima di questa istruzione è "visibile" al codice del thread che si sta avviando.
    In modo opposto:
    Dato un t1.join(), è GARANTITO che tutto quello fatto dal thread t1 è "visibile" al codice dopo questa istruzione.

    Questi due punti in sostanza sono il motivo per cui un codice come quello che hai postato può funzionare senza una evidente/esplicita sincronizzazione.
Devi accedere o registrarti per scrivere nel forum
1 risposte