Roscas de bloqueo Mutex


Soy nuevo en la programación multihilo/procesos. Así que esto es lo que necesito aclarar.

Procesar Un código

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

Con el pseudo código anterior, es el proceso B capaz de acceder a sharedResource si mutex no está desbloqueado?

¿Cómo puedo acceder correctamente al sharedResource desde el proceso B?

¿Hay algún diagrama visual claro que explique la relación entre mutexes, hilos y procesos?

Author: resting, 2013-02-15

4 answers

Lo que necesitas hacer es llamar a pthread_mutex_lock para asegurar un mutex, así:

pthread_mutex_lock(&mutex);

Una vez que hagas esto, cualquier otra llamada a pthread_mutex_lock(mutex) no volverá hasta que llames a pthread_mutex_unlock en este hilo. Así que si intentas llamar a pthread_create, podrás crear un nuevo subproceso, y ese subproceso podrá usar (incorrectamente) el recurso compartido. Debe llamar a pthread_mutex_lock desde su función fooAPI, y eso hará que la función espere hasta que el recurso compartido sea disponible.

Así que tendrías algo como esto:

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

Editar: El uso de recursos entre procesos sigue este mismo enfoque básico, pero necesita mapear la memoria en su otro proceso. Aquí hay un ejemplo usando 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");
}

Escribir el programa para hacer cambios en p->sharedResource se deja como un ejercicio para el lector. :-)

Se olvidó de notar, por cierto, que el mutex tiene que tener el atributo PTHREAD_PROCESS_SHARED establecido, para que pthreads funcione a través procesa.

 39
Author: Brian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 07:40:42

Q1.) Suponiendo que el proceso B intenta tomar posesión del mismo mutex que bloqueó en el proceso A (lo dejó fuera de su pseudocódigo) entonces no, el proceso B no puede acceder a sharedResource mientras el mutex está bloqueado, ya que se quedará esperando para bloquear el mutex hasta que sea liberado por el proceso A. Regresará de la función mutex_lock () cuando el mutex esté bloqueado (o cuando ocurra un error!)

Q2.) En el Proceso B, asegúrese de bloquear siempre el mutex, acceder al recurso compartido y, a continuación, desbloquear el mutex. Además, verifique el código de retorno de la rutina mutex_lock( pMutex) para asegurarse de que realmente posee el mutex, y SOLO desbloquee el mutex si lo ha bloqueado. Haga lo mismo desde el proceso A.

Ambos procesos deberían hacer básicamente lo mismo al acceder al mutex.
bloqueo() Si el bloqueo tiene éxito, entonces { acceso a sharedResource desbloquear() }

Q3.) Sí, hay muchos diagramas: =) 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
Author: c.fogelklou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 04:37:39

Un proceso consiste en al menos un hilo (piense en la función principal). El código multihilo solo generará más hilos. Los mutexes se utilizan para crear bloqueos alrededor de los recursos compartidos para evitar la corrupción de datos / comportamiento inesperado / no deseado. Básicamente, proporciona la ejecución secuencial en una configuración asíncrona, cuyo requisito se deriva de operaciones no atómicas no constantes en estructuras de datos compartidas.

Una descripción vívida de lo que los mutexes serían el caso de las personas (hilos) hacer cola para visitar el baño (recurso compartido). Mientras una persona (hilo) está usando el baño aliviándose (operación no-constante no-atómica), él/ella debe asegurarse de que la puerta está cerrada (mutex), de lo contrario podría llevar a ser atrapado en pleno monty (comportamiento no deseado)

 2
Author: Aditya Sihag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-15 04:41:11

A continuación, el fragmento de código, le ayudará a comprender el concepto mutex-lock-unlock. Prueba el código. (además, al variar el tiempo de espera y el tiempo de proceso, puede desarrollar su comprensión).

Código para su referencia:

#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;
}
 2
Author: parasrish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-07 11:56:34