Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it L'avatar di ibykos
    Registrato dal
    Feb 2005
    Messaggi
    201

    [C]Uso dei semafori con windows

    Il mio problema attuale è riuscire a fare condividere una variabile a due thread concorrenti in ambiente Windows.
    Ho trovato delle funzioni interessanti (la CreateMutex, la WaiForSingleObject e la ReleaseMutex) ma non sono ancora riuscito a trovarne una che faccia diventare "rosso" il semaforo di mutua esclusione.

    codice:
    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    DWORD WINAPI concurrent (void *);
    
    HANDLE full,
           empty,
           conc;
           
    int id;
    LPDWORD ID=(LPDWORD)&id;
           
    int main (){
        
        char c=' ';
        
        full=CreateMutex(NULL,TRUE,"full"); /*semaforo inizia occupato*/
        empty=CreateMutex(NULL,FALSE,"empty");/*questo inizia libero*/
        
        conc = CreateThread(NULL,0,concurrent,NULL,0,ID);/*lancio thread*/
        
        if (conc==NULL)
            printf("creazione thread fallita\n");
        
        while (TRUE){
            
            WaitForSingleObject(empty,INFINITE); /*aspetto empty==TRUE*/
            
            /*eventuale regione critica*/
            
            ReleaseMutex(full);
            
        }    
        
        return 0;
    }    
    
    DWORD WINAPI concurrent (void * dati){
        
        printf ("inizio TRUE=%d\n",TRUE);
        
        while (TRUE){
            
            WaitForSingleObject(full,INFINITE);
            
            /*eventuale regione critica*/
    
            printf ("stampo\n");
            
            ReleaseMutex(empty);
            
        }    
        
        TerminateThread(conc,0);
    }
    Inquesto codice potete vedere che mi manca una funzione mutex_lock o simile per poter tagliare fuori un thread da una eventuale regione critica.
    Ho trovato la funzione CloseHandle, ma non riesco a farla funzionare come voglio io.
    Fatemi sapere

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    Quale e' la variabile che vorresti condividere ?

    Perche' non usi una CriticalSection ?

    Perche' usi la TerminateThread (che si usa per forzare il termine del thread ...) quando il thread sta per terminare "naturalmente" ?

  3. #3
    Utente di HTML.it L'avatar di ibykos
    Registrato dal
    Feb 2005
    Messaggi
    201
    Quale e' la variabile che vorresti condividere ?

    Una variabile, non importa quale, oppure implementare il modello produttore/consumatore ... in generale mi serve una funzione di lock per il semaforo.

    Perche' non usi una CriticalSection ?

    Perché non so come si fa sotto Windows, se hai un link a qualche libreria, te ne sarei grato.

    Perche' usi la TerminateThread (che si usa per forzare il termine del thread ...) quando il thread sta per terminare "naturalmente" ?

    Rimasuglio di vari esperimenti, in cui volevo controllare la morte di un thread dall'altro.

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    Qualcosa del genere

    codice:
    CRITICAL_SECTION cs;
           
    int main ()
    {
        InitializeCriticalSection(&cs);
    
        unsigned long ID;
        HANDLE conc =  CreateThread(NULL,0,concurrent,NULL,0,&ID);/*lancio thread*/
        
        if (conc==NULL)
            printf("creazione thread fallita\n");
        
        while (TRUE)
        {
    	EnterCriticalSection(&cs);
    	
            // regione critica	
    	printf("Main Thread\n");
    		
            LeaveCriticalSection(&cs);
        }    
        
    	DeleteCriticalSection(&cs);
        return 0;
    }    
    
    DWORD WINAPI concurrent (void * dati){
        
        printf ("inizio TRUE=%d\n",TRUE);
        
        while (TRUE)
        {
            
    	EnterCriticalSection(&cs);
    	
    	// regione critica
    	printf("Thread 2\n");
    
            LeaveCriticalSection(&cs); 
        }    
    }

  5. #5
    Utente di HTML.it L'avatar di ibykos
    Registrato dal
    Feb 2005
    Messaggi
    201

    [C]I semafori nell'OS windows

    Chi ha studiato a scuola il sistema operativo Unix, è abituato a considerare i semafori come un servizio fornito dal sistema operativo in grado di proteggere una variabile condivisa e, allo stesso tempo, di organizzare i processi che vogliono accederci in maniera tale da non sprecare tempo e risorse.
    Premetto un po' di teoria perché mi serve per il domandone finale
    Ad un semaforo è associato un contatore, gestito dal Kernel, il quale parte dal valore 0, che viene considerato "risorsa libera".
    Il primo processo che vuole accedere alla variabile associata al semaforo chiama la funzione wait(semaforo), la quale non fa altro che verificare se il contatore è almeno uguale a 0 (test passato in questo caso) e decrementarlo.
    Un secondo processo prova ad impossessarsi della risorsa, già occupata, ma questa volta non supera il test, così il Kernel lo mette a dormire in attesa che si liberi il posto.
    Il posto si libera nel momento in cui viene chiama la signal(semaforo), la quale incrementa il contatore del semaforo e, se lo trova almeno uguale a 0, sveglia un processo in attesa nella ready list.
    Ora, per come ho esposto qui, i semafori dipendono dal Kernel, pertanto una implementazione di questo tipo (in pseudocodice) risolve il problema del produttore/consumatore, in cui i due processi concorrenti devono essere sincronizzati in maniera tale da funzionare uno alla volta.

    codice:
    /*produttore*/
    
    while(TRUE){
    
        wait (empty); /*aspetta che il buffer sia vuoto*/
    
        write (buffer); 
    
        signal (full) /*segnala che  il buffer è pieno*/
    
    }
    
    /*consumatore*/
    
    while(TRUE){
    
        wait(full);  /*aspetta che il buffer sia pieno*/
    
        print(buffer);
    
        signal(empty); /*segnala che il buffer è vuoto*/
    }
    Ora, se provate ad implementare questa soluzione con le funzioni della libreria windows.h

    WaitForSingleObject
    ReleaseMutex

    Potrete osservare che in realtà non funziona, perché i processi non si bloccano sulla WaitForSingleObject dopo aver iterato una prima volta.

    Adesso invece vi propongo il normale schema di protezione di una variabile mediante i semafori.

    codice:
    while(TRUE){
    
        wait(libero);  /*aspetta che la risorsa sia libera*/
    
        usa(risorsa);
    
        signal(libero); /*segnala che non ha più bisogno della risorsa*/
    }
    Implementando questa soluzione in un programma con numerosi thread con le funzioni viste sopra funziona tutto correttamente.


    La conclusione a cui sono giunto è la seguente: la WaitForSingleObject associa un semaforo ad un processo (cosa che nel modell oche ho mostrato non avviene), il quale troverà sempre via libera ogni volta che chiama questa funzione (invece nel modello unix si blocca la seconda volta che lo chiama) e non molla il semaforo finché non chiama la ReleaseMutex.
    Per risolvere il problema del produttore consumatore quindi si potrebbe usare una strategia di questo tipo (sempre in pseudocodice):

    codice:
    semaforo mutex;
    int full;
    
    /*produttore*/
    
    while (TRUE){
    
        WaitForSingleobject(mutex);
    
        if (full==FALSE){
            write(buffer);
            full=TRUE;
            ReleaseMutex(mutex);
        }
        else {
             SvegliaThread(lista_di_thread);
             ReleaseMutex(mutex);
        }
    
    /*consumatori*/
    
    while (TRUE){
    
        WaitForSingleObject(mutex);
    
        if (full==TRUE){
            print(buffer);
            full=FALSE;
            ReleaseMutex(mutex);
        }
        else {
            ReleaseMutex(mutex);
            SospendiThread(lista_di_thread)
        }
    
    }
    dove la SospendiThread e la svegliaThread sono pensate in modo da gestire più thread contemporaneamente.

    Domande:

    L'ipotesi di funzionamento che ho fatto è corretta?
    Questa soluzione è efficiente?
    Ne esistono di migliori?

    a voi.

  6. #6
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    Domanda:

    perche' con Windows usi i mutex e non i semafori?

    Un mutex e' un tipo diverso di oggetto di sincronizzazione da un semaforo ...

    In Windows puoi creare un mutex tramite

    CreateMutex

    o un semaforo con

    CreateSemaphore

    Vedi se fa al caso tuo quest'ultimo oggetto

    http://msdn.microsoft.com/library/de...re_objects.asp

  7. #7
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,296

    Moderazione

    Ho unito le discussioni aperte sullo stesso argomento ("i semafori di Windows"); non creiamo dispersione aprendo discussioni sullo stesso identico argomento.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  8. #8
    Utente di HTML.it L'avatar di ibykos
    Registrato dal
    Feb 2005
    Messaggi
    201
    Effettivamente i due post riguardavano lo stesso problema, ma il primo era la richiesta di una soluzione, mentre il secondo speravo diventasse l'inizio di una discussione più ampia su come si gestisce la concorrenza di processi mediante semafori in windows.
    Comunque sia, grazie Oregon per l'aiuto

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.