Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Algoritmi - Sincronizzazione dei processi
Forum - Algoritmi - Sincronizzazione dei processi

Avatar
MagoAntò (Normal User)
Rookie


Messaggi: 42
Iscritto: 07/02/2009

Segnala al moderatore
Postato alle 17:48
Mercoledì, 15/05/2013
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):

Codice sorgente - presumibilmente C++

  1. AREA DATI:
  2.  
  3.     N // #numero processi client
  4.  
  5.     mutex produttore [3] = 0  // array di semafori binari per risvegliare i produttori
  6.  
  7.     struct client
  8.     {
  9.        boolean previous_char [3] = false;
  10.        int contatore = 0;
  11.     };
  12.  
  13.     typedef struct client CLIENTE;
  14.  
  15.     CLIENTE [N]; // array di struct CLIENTE relativo ai client;
  16.  
  17.     CODICE:
  18.  
  19.     CONTROLLORE_S ()
  20.     {
  21.        while (true)
  22.        {
  23.           wait (mutex_1);
  24.           X = rand() %3 +1; // scelgo a caso il produttore
  25.           signal (mutex_1);
  26.           signal (produttore[X]); // risveglio il produttore X
  27.        }
  28.     }
  29.  
  30.     PRODUTTORE ()
  31.     {
  32.        wait (produttore[X]); // aspetto la scelta del produttore
  33.        
  34.        wait (mutex_2)
  35.        genera_char(Y); // genero un carattere e lo memorizzo in Y
  36.        signal (carattere_generato);
  37.        signal (mutex_2);
  38.        
  39.     }
  40.  
  41.     CLIENT ()
  42.     {
  43.        while (CLIENTE[i].contatore < 3)
  44.        {
  45.           wait (carattere_generato);
  46.           wait (mutex_3);
  47.           if ((Y == 'A') && (CLIENTE[i].previous_char[1] == false)) // il carattere generato è A e    
  48.  
  49.                       il client non l'ha letto prima
  50.          {
  51.             read_char_y();
  52.             CLIENTE[i].previous_char[1] = true;
  53.          }
  54.          else if ((Y == 'B') && (CLIENTE[i].previous_char[2] == false)) // il carattere generato è
  55.  
  56.                         B e il client non l'ha letto prima
  57.           {
  58.              read_char_y();
  59.              CLIENTE[i].previous_char[2] = true;
  60.           }
  61.           else (Y == 'C') && (CLIENTE[i].previous_char[3] == false)) // il carattere generato è      
  62.  
  63.     C e il client non l'ha letto prima
  64.          {
  65.             read_char_y();
  66.             CLIENTE[i].previous_char[3] = true;
  67.          }
  68.          signal (mutex_3);
  69.       }
  70.    }



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:
Codice sorgente - presumibilmente C++

  1. AREA DATI:
  2.  
  3.     N // #numero processi client
  4.  
  5.     mutex produttore [3] = 1 // array di semafori binari per verificare se il produttore scelto è libero
  6.     mutex carattere_generato [3] = 0  // array di semafori binari per risvegliare il produttore selezionato
  7.  
  8.     struct client
  9.     {
  10.        boolean previous_char [3] = false;
  11.        int contatore = 0;
  12.             mutex client_libero = 1; // semaforo binario per indicare se il client è libero o no
  13.     };
  14.  
  15.     typedef struct client CLIENTE;
  16.  
  17.     CLIENTE [N]; // array di struct CLIENTE relativo ai client;
  18.  
  19.  
  20.  
  21.     CONTROLLORE_S ()
  22.     {
  23.        while (true)
  24.        {
  25.           wait (mutex_1);
  26.           X = rand() %3 +1; // scelgo a caso il produttore
  27.                     signal (mutex_1);
  28.           wait (produttore[X]); // aspetto che il produttore X sia libero
  29.           signal (carattere_generato[X]); // risveglio il produttore X
  30.        }
  31.     }
  32.  
  33.     PRODUTTORE ()
  34.     {
  35.        wait (carattere_generato[X]); // aspetto che ci sia il carattere
  36.        
  37.        wait (mutex_2)
  38.        genera_char(Y); // genero un carattere e lo memorizzo in Y
  39.        wait (CLIENTE.client_libero[i]); //aspetto che ci sia almeno un client in attesa
  40.        signal (carattere_generato);
  41.        signal (mutex_2);
  42.        signal (produttore[X]); // il produttore X è libero
  43.        
  44.     }
  45.  
  46.     CLIENT ()
  47.     {
  48.        while (CLIENTE[i].contatore < 3)
  49.        {
  50.           wait (carattere_generato);
  51.           wait (mutex_3);
  52.           if ((Y == 'A') && (CLIENTE[i].previous_char[1] == false)) // il carattere generato è A e    
  53.  
  54.                       il client non l'ha letto prima
  55.          {
  56.             read_char_y();
  57.             CLIENTE[i].previous_char[1] = true;
  58.          }
  59.          else if ((Y == 'B') && (CLIENTE[i].previous_char[2] == false)) // il carattere generato è
  60.  
  61.                         B e il client non l'ha letto prima
  62.           {
  63.              read_char_y();
  64.              CLIENTE[i].previous_char[2] = true;
  65.           }
  66.           else (Y == 'C') && (CLIENTE[i].previous_char[3] == false)) // il carattere generato è      
  67.  
  68.     C e il client non l'ha letto prima
  69.          {
  70.             read_char_y();
  71.             CLIENTE[i].previous_char[3] = true;
  72.          }
  73.          signal (mutex_3);
  74.          signal (CLIENTE.client_libero[i]); // il client i-simo è libero
  75.       }
  76.    }



Che ne dite?

Grazie in anticipo per le risposte! ;)

PM Quote