2013-02-15 20 views
17

Sono nuovo alla programmazione multi threaded/processs. Quindi ecco cosa ho bisogno di chiarire.Thread lock mutex

processo Un codice

pthread_mutex_lock() 
    pthread_create(fooAPI(sharedResource)) //fooAPI creates another thread with shared resource that shares across processes. 
pthread_mutex_unlock() 

Con il codice pseudo sopra, è processo B in grado di accedere sharedResource se mutex non è sbloccato?

Come posso accedere correttamente a sharedResource dal processo B?

C'è qualche schema visivo chiaro che spiega la relazione tra mutex, thread e processi?

risposta

30

Quello che dovete fare è chiamare pthread_mutex_lock per garantire un mutex, come questo:

pthread_mutex_lock(&mutex); 

Una volta fatto questo, tutti gli altri chiamate a pthread_mutex_lock(mutex) non tornerà fino a quando si chiama pthread_mutex_unlock in questo thread. Quindi, se provi a chiamare pthread_create, sarai in grado di creare un nuovo thread e quel thread sarà in grado (erroneamente) di utilizzare la risorsa condivisa. Dovresti chiamare pthread_mutex_lock dalla tua funzione fooAPI e questo farà sì che la funzione attenda fino a quando la risorsa condivisa non sarà disponibile.

Così si avrebbe qualcosa di simile:

#include <pthread.h> 
#include <stdio.h> 

int sharedResource = 0; 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

void* fooAPI(void* param) 
{ 
    pthread_mutex_lock(&mutex); 
    printf("Changing the shared resource now.\n"); 
    sharedResource = 42; 
    pthread_mutex_unlock(&mutex); 
    return 0; 
} 

int main() 
{ 
    pthread_t thread; 

    // Really not locking for any reason other than to make the point. 
    pthread_mutex_lock(&mutex); 
    pthread_create(&thread, NULL, fooAPI, NULL); 
    sleep(1); 
    pthread_mutex_unlock(&mutex); 

    // Now we need to lock to use the shared resource. 
    pthread_mutex_lock(&mutex); 
    printf("%d\n", sharedResource); 
    pthread_mutex_unlock(&mutex); 
} 

Edit: L'utilizzo di risorse attraverso i processi di seguito lo stesso approccio di base, ma è necessario mappare la memoria nel vostro altro processo. Ecco un esempio utilizzando shmem:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/file.h> 
#include <sys/mman.h> 
#include <sys/wait.h> 

struct shared { 
    pthread_mutex_t mutex; 
    int sharedResource; 
}; 

int main() 
{ 
    int fd = shm_open("/foo", O_CREAT | O_TRUNC | O_RDWR, 0600); 
    ftruncate(fd, sizeof(struct shared)); 

    struct shared *p = (struct shared*)mmap(0, sizeof(struct shared), 
     PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 

    p->sharedResource = 0; 

    // Make sure it can be shared across processes 
    pthread_mutexattr_t shared; 
    pthread_mutexattr_init(&shared); 
    pthread_mutexattr_setpshared(&shared, PTHREAD_PROCESS_SHARED); 

    pthread_mutex_init(&(p->mutex), &shared); 

    int i; 
    for (i = 0; i < 100; i++) { 
     pthread_mutex_lock(&(p->mutex)); 
     printf("%d\n", p->sharedResource); 
     pthread_mutex_unlock(&(p->mutex)); 
     sleep(1); 
    } 

    munmap(p, sizeof(struct shared*)); 
    shm_unlink("/foo"); 
} 

Scrivendo il programma di apportare modifiche al p-> RisorsaCondivisa è lasciata come esercizio per il lettore. :-)

Ho dimenticato, tra l'altro, che il mutex deve avere l'attributo PTHREAD_PROCESS_SHARED impostato, in modo che i pthread funzionino attraverso i processi.

+0

Questo è molto chiaro. Potresti includere anche un esempio di come Process B, che è un'altra applicazione, possa accedere a sharedResource? – resting

2

Q1). Assumendo che il processo B provi ad assumere la proprietà dello stesso mutex che hai bloccato nel processo A (hai lasciato fuori dallo pseudocodice) allora no, il processo B non può accedere a sharedResource mentre il mutex è bloccato poiché siederà in attesa per bloccare il mutex finché non viene rilasciato dal processo A. Verrà ripristinato dalla funzione mutex_lock() quando il mutex è bloccato (o quando si verifica un errore!)

Q2.) In Processo B, assicurarsi di bloccare sempre il mutex, accedere alla risorsa condivisa e quindi sbloccare il mutex. Inoltre, controlla il codice di ritorno dalla routine mutex_lock (pMutex) per assicurarti di possedere il mutex e SOLO sbloccare il mutex se lo hai bloccato. Fare lo stesso dal processo A.

Entrambi i processi dovrebbero fondamentalmente fare la stessa cosa quando si accede al mutex.
lock() Se il blocco ha successo, allora { accesso RisorsaCondivisa sblocco() }

Q3) Sì, ci sono un sacco di diagrammi:. =) https://www.google.se/search?q=mutex+thread+process&rlz=1C1AFAB_enSE487SE487&um=1&ie=UTF-8&hl=en&tbm=isch&source=og&sa=N&tab=wi&ei=ErodUcSmKqf54QS6nYDoAw&biw=1200&bih=1730&sei=FbodUbPbB6mF4ATarIBQ

1

Un processo consiste di almeno un thread (pensa alla funzione principale). Il codice multi-thread genera solo più thread. I mutex vengono utilizzati per creare blocchi attorno a risorse condivise per evitare il danneggiamento dei dati/comportamento imprevisto/indesiderato. Fondamentalmente fornisce l'esecuzione sequenziale in un setup asincrono - il requisito per cui deriva da operazioni non atomiche non-const su strutture dati condivise.

Una vivida descrizione di quali mutex sarebbe il caso di persone (discussioni) in fila per visitare il bagno (risorsa condivisa). Mentre una persona (thread) sta usando il bagno che si sta calmando (operazione non atomica non-const), deve assicurarsi che la porta sia bloccata (mutex), altrimenti potrebbe portare a essere catturato in pieno monty (comportamento indesiderato)

2

Di seguito, lo snippet di codice, ti aiuterà a comprendere il concetto di mutex-lock-unlock. Tentativo di funzionamento a secco sul codice. (inoltre, variando il tempo di attesa e il tempo di elaborazione, puoi farti capire).

Codice per il vostro riferimento:

#include <stdio.h> 
#include <pthread.h> 

void in_progress_feedback(int); 

int global = 0; 
pthread_mutex_t mutex; 
void *compute(void *arg) { 

    pthread_t ptid = pthread_self(); 
    printf("ptid : %08x \n", (int)ptid);  

    int i; 
    int lock_ret = 1; 
    do{ 

     lock_ret = pthread_mutex_trylock(&mutex); 
     if(lock_ret){ 
      printf("lock failed(%08x :: %d)..attempt again after 2secs..\n", (int)ptid, lock_ret); 
      sleep(2); //wait time here.. 
     }else{ //ret =0 is successful lock 
      printf("lock success(%08x :: %d)..\n", (int)ptid, lock_ret); 
      break; 
     } 

    } while(lock_ret); 

     for (i = 0; i < 10*10 ; i++) 
     global++; 

    //do some stuff here 
    in_progress_feedback(10); //processing-time here.. 

    lock_ret = pthread_mutex_unlock(&mutex); 
    printf("unlocked(%08x :: %d)..!\n", (int)ptid, lock_ret); 

    return NULL; 
} 

void in_progress_feedback(int prog_delay){ 

    int i=0; 
    for(;i<prog_delay;i++){ 
    printf(". "); 
    sleep(1); 
    fflush(stdout); 
    } 

    printf("\n"); 
    fflush(stdout); 
} 

int main(void) 
{ 
    pthread_t tid0,tid1; 
    pthread_mutex_init(&mutex, NULL); 
    pthread_create(&tid0, NULL, compute, NULL); 
    pthread_create(&tid1, NULL, compute, NULL); 
    pthread_join(tid0, NULL); 
    pthread_join(tid1, NULL); 
    printf("global = %d\n", global); 
    pthread_mutex_destroy(&mutex); 
      return 0; 
} 
+0

La funzione void * compute() viene eseguita solo quando viene chiamata o esiste un modo per avviare questo thread in modo che esegua continuamente questa funzione in background? – LandonZeKepitelOfGreytBritn

+0

quando un thread viene generato, il metodo associato al thread spawn inizia ad essere eseguito sul thread (in questo caso 'compute()'). Se non viene generato alcun thread, si è ancora in main-thread (dove 'main()' viene eseguito). Ora, se devi fare in modo che il thread esegua qualcosa in background, devi mantenere quell'esecuzione sul metodo associato, su una condizione di non uscita (es. Non lasciare che il metodo associato esca, finché non chiedi di chiudere. la condizione di uscita quando viene segnalato al thread, deve uscire (pulizia ecc.), altrimenti deve rimanere per eseguire l'operazione/i desiderata. – parasrish

Problemi correlati