web-dev-qa-db-fra.com

Filetage de verrouillage Mutex

Suis nouveau dans la programmation multi-thread/processus. Voici donc ce que je dois clarifier.

Traiter un code

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

Avec le pseudo-code ci-dessus, le processus B peut-il accéder à sharedResource si mutex n'est pas déverrouillé?

Comment puis-je accéder correctement à sharedResource à partir du processus B?

Y a-t-il un diagramme visuel clair qui explique la relation entre les mutex, les threads et les processus?

28
resting

Ce que vous devez faire est d'appeler pthread_mutex_lock pour sécuriser un mutex, comme ceci:

pthread_mutex_lock(&mutex);

Une fois que vous faites cela, tous les autres appels à pthread_mutex_lock(mutex) ne reviendront pas jusqu'à ce que vous appeliez pthread_mutex_unlock Dans ce fil. Donc, si vous essayez d'appeler pthread_create, vous pourrez créer un nouveau thread et ce thread pourra (incorrectement) utiliser la ressource partagée. Vous devez appeler pthread_mutex_lock À partir de votre fonction fooAPI, et cela fera attendre la fonction jusqu'à ce que la ressource partagée soit disponible.

Vous auriez donc quelque chose comme ceci:

#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);
}

Modifier: l'utilisation des ressources entre les processus suit cette même approche de base, mais vous devez mapper la mémoire dans votre autre processus. Voici un exemple d'utilisation de 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");
}

L'écriture du programme pour apporter des modifications à p-> sharedResource est laissée en exercice au lecteur. :-)

J'ai oublié de noter, en passant, que le mutex doit avoir l'attribut PTHREAD_PROCESS_SHARED, afin que pthreads fonctionne à travers les processus.

50
Brian

Q1.) En supposant que le processus B tente de s'approprier le même mutex que vous avez verrouillé dans le processus A (vous l'avez laissé hors de votre pseudocode), alors non, le processus B ne peut pas accéder à sharedResource pendant que le mutex est verrouillé car il attendra pour verrouiller le mutex jusqu'à ce qu'il soit libéré par le processus A. Il reviendra de la fonction mutex_lock () lorsque le mutex est verrouillé (ou lorsqu'une erreur se produit!)

Q2.) Dans le processus B, assurez-vous de toujours verrouiller le mutex, d'accéder à la ressource partagée, puis de déverrouiller le mutex. Vérifiez également le code retour de la routine mutex_lock (pMutex) pour vous assurer que vous êtes bien le propriétaire du mutex et déverrouillez UNIQUEMENT le mutex si vous l'avez verrouillé. Faites de même à partir du processus A.

Les deux processus devraient essentiellement faire la même chose lors de l'accès au mutex.
lock () Si le verrouillage réussit, alors {access sharedResource unlock ()}

Q3.) Oui, il existe de nombreux diagrammes: =) 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

3
c.fogelklou

Ci-dessous, un extrait de code, vous aidera à comprendre le concept mutex-lock-unlock. Essayez d'effectuer un essai à blanc sur le code. (De plus, en variant le temps d'attente et le temps de traitement, vous pouvez vous faire comprendre).

Code pour votre référence:

#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;
}
3
parasrish

Un processus se compose d'au moins un thread (pensez à la fonction principale). Le code multi-thread ne fera que générer plus de threads. Les mutex sont utilisés pour créer des verrous autour des ressources partagées afin d'éviter la corruption des données/un comportement inattendu/indésirable. Fondamentalement, il prévoit une exécution séquentielle dans une configuration asynchrone - dont l'exigence découle d'opérations non atomiques non constantes sur des structures de données partagées.

Une description vivante de quels mutex serait le cas des personnes (fils) faisant la queue pour visiter les toilettes (ressource partagée). Tandis qu'une personne (fil) utilise la salle de bain pour se détendre (opération non atomique non constante), il/elle doit s'assurer que la porte est verrouillée (mutex), sinon cela pourrait conduire à être pris en pleine monty (comportement indésirable )

3
Aditya Sihag