Oppure

Loading
15/05/13 15:48
MagoAntò
Ciao a tutti!

Sto facendo degli esercizi sulla sincronizzazione dei processi ma ho alcuni dubbi (chiedo scusa in anticipo se dovessero essere domande un po' banali, ma sono davvero nel pallone).

Vi scrivo la traccia del primo esercizio: "Un sistema è costituito da un processo controllore (S), tre processi produttori di caratteri (A, B e C) ed N processi client che devono leggere i tre caratteri, una sola volta, prima di terminare l'esecuzione. S decide in maniera casuale quale dei tre processi produttori deve produrre il prossimo carattere e scrive la scelta in un'area di memoria X. I tre processi produttori accedono ad X per scoprire chi dovrà produrre il prossimo carattere e quello prescelto inserisce il carattere in un'area di memoria Y. I client accedono ad Y in maniera esclusiva. Un client che non ha precedentemente letto il carattere contenuto in Y lo preleva, altrimenti libera la risorsa e torna in attesa di un nuovo carattere."

Questo è il mio svolgimento (come pseudocodice fa un po' pena, mi rendo conto):

    AREA DATI:

    N // #numero processi client

    mutex produttore [3] = 0  // array di semafori binari per risvegliare i produttori

    struct client
    {
       boolean previous_char [3] = false;
       int contatore = 0;
    };

    typedef struct client CLIENTE;

    CLIENTE [N]; // array di struct CLIENTE relativo ai client;

    CODICE:

    CONTROLLORE_S ()
    {
       while (true)
       {
          wait (mutex_1);
          X = rand() %3 +1; // scelgo a caso il produttore
          signal (mutex_1);
          signal (produttore[X]); // risveglio il produttore X
       }
    }

    PRODUTTORE ()
    {
       wait (produttore[X]); // aspetto la scelta del produttore
       
       wait (mutex_2)
       genera_char(Y); // genero un carattere e lo memorizzo in Y
       signal (carattere_generato);
       signal (mutex_2);
       
    }

    CLIENT ()
    {
       while (CLIENTE[i].contatore < 3)
       {
          wait (carattere_generato);
          wait (mutex_3);
          if ((Y == 'A') && (CLIENTE[i].previous_char[1] == false)) // il carattere generato è A e    

                      il client non l'ha letto prima
          {
             read_char_y();
             CLIENTE[i].previous_char[1] = true;
          }
          else if ((Y == 'B') && (CLIENTE[i].previous_char[2] == false)) // il carattere generato è

                         B e il client non l'ha letto prima
          {
             read_char_y();
             CLIENTE[i].previous_char[2] = true;
          }
          else (Y == 'C') && (CLIENTE[i].previous_char[3] == false)) // il carattere generato è       

    C e il client non l'ha letto prima
          {
             read_char_y();
             CLIENTE[i].previous_char[3] = true;
          }
          signal (mutex_3);
       }
    }


Il mio dubbio è questo: mettiamo caso che il controllore S generi il numero 1 e che voglia notificare al produttore 1 che deve produrre il carattere. Mettiamo sempre caso che, al momento della signal, il produttore 1 è nella sua sezione critica. A rigor di logica, la signal del controllore S andrebbe "persa" visto che non c'è nessun processo bloccato su quel semaforo, giusto? Stesso discorso per la comunicazione produttore-client. Premetto che è un caso molto limite e, ripeto, non so se è un ragionamento corretto: immaginiamo ci sia un client in sezione critica e che tutti gli altri client siano in attesa sul mutex_3; nel frattempo, uno dei produttori genera un carattere e fa una signal per notificare la cosa ad uno dei client. Anche qui, la signal del produttore andrebbe persa perchè non c'è nessun client in attesa su [c]carattere_generato[/c], giusto?

Se tutto questo è giusto, sarebbe preferibile ragionare così? Vanno creati altri semafori di controllo, opportunamente inizializzati ed inseriti nel codice, per aspettare che il produttore scelto sia disponibile per l'ascolto (così da non "sprecare" nessuna signal) e per aspettare che almeno un client sia in ascolto? Diciamo una cosa del genere:
    AREA DATI:

    N // #numero processi client

    mutex produttore [3] = 1 // array di semafori binari per verificare se il produttore scelto è libero
    mutex carattere_generato [3] = 0  // array di semafori binari per risvegliare il produttore selezionato

    struct client
    {
       boolean previous_char [3] = false;
       int contatore = 0;
            mutex client_libero = 1; // semaforo binario per indicare se il client è libero o no
    };

    typedef struct client CLIENTE;

    CLIENTE [N]; // array di struct CLIENTE relativo ai client;



    CONTROLLORE_S ()
    {
       while (true)
       {
          wait (mutex_1);
          X = rand() %3 +1; // scelgo a caso il produttore
                    signal (mutex_1);
          wait (produttore[X]); // aspetto che il produttore X sia libero
          signal (carattere_generato[X]); // risveglio il produttore X
       }
    }

    PRODUTTORE ()
    {
       wait (carattere_generato[X]); // aspetto che ci sia il carattere
       
       wait (mutex_2)
       genera_char(Y); // genero un carattere e lo memorizzo in Y
       wait (CLIENTE.client_libero[i]); //aspetto che ci sia almeno un client in attesa
       signal (carattere_generato);
       signal (mutex_2);
       signal (produttore[X]); // il produttore X è libero
       
    }

    CLIENT ()
    {
       while (CLIENTE[i].contatore < 3)
       {
          wait (carattere_generato);
          wait (mutex_3);
          if ((Y == 'A') && (CLIENTE[i].previous_char[1] == false)) // il carattere generato è A e    

                      il client non l'ha letto prima
          {
             read_char_y();
             CLIENTE[i].previous_char[1] = true;
          }
          else if ((Y == 'B') && (CLIENTE[i].previous_char[2] == false)) // il carattere generato è

                         B e il client non l'ha letto prima
          {
             read_char_y();
             CLIENTE[i].previous_char[2] = true;
          }
          else (Y == 'C') && (CLIENTE[i].previous_char[3] == false)) // il carattere generato è       

    C e il client non l'ha letto prima
          {
             read_char_y();
             CLIENTE[i].previous_char[3] = true;
          }
          signal (mutex_3);
          signal (CLIENTE.client_libero[i]); // il client i-simo è libero
       }
    }


Che ne dite?

Grazie in anticipo per le risposte! ;)
aaa