pthread_create - Hilos de bloqueo mutex
pthread_join (4)
A continuación, el fragmento de código, le ayudará a comprender el concepto mutex-lock-unlock. Intente ejecutar en seco el código. (Además, al variar el tiempo de espera y el tiempo de proceso, puede aumentar 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;
}
Soy nuevo en la programación de multiproceso / procesos. Así que esto es lo que necesito aclarar.
Código de proceso A
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, ¿el proceso B puede acceder a sharedResource
si mutex no está desbloqueado?
¿Cómo puedo acceder correctamente al recurso compartido desde el proceso B?
¿Hay algún diagrama visual claro que explique la relación entre mutexes, hilos y procesos?
Lo que debes hacer es llamar a pthread_mutex_lock para asegurar un mutex, como este:
pthread_mutex_lock(&mutex);
Una vez que haga esto, cualquier otra llamada a pthread_mutex_lock(mutex)
no regresará hasta que llame a pthread_mutex_unlock
en este hilo. Entonces, si intenta llamar a pthread_create, podrá crear un nuevo hilo, y ese hilo podrá usar (incorrectamente) el recurso compartido. Debería llamar a pthread_mutex_lock
desde su función fooAPI
, y eso hará que la función espere hasta que el recurso compartido esté disponible.
Entonces 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);
}
Edición: el uso de recursos en todos los procesos sigue este mismo enfoque básico, pero debe asignar la memoria a 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 realizar cambios en p-> sharedResource se deja como un ejercicio para el lector. :-)
Por cierto, se olvidó de señalar que el mutex debe tener el conjunto de atributos PTHREAD_PROCESS_SHARED, de modo que los pthreads funcionen en todos los procesos.
Q1.) Suponiendo que el proceso B intenta apropiarse 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 recursos compartidos compartidos mientras que el mutex está bloqueado ya que estará esperando el bloqueo del 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 luego 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. Haz lo mismo del proceso A.
Ambos procesos deberían básicamente hacer lo mismo al acceder al mutex.
bloqueo () Si el bloqueo se realiza correctamente, entonces {access sharedResource unlock ()}
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
Un proceso consiste en al menos un hilo (piense en la función principal). El código de múltiples hilos 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, el requisito para el cual se deriva de operaciones no atómicas no constantes en estructuras de datos compartidas.
Una descripción vívida de lo que sería la exclusión mutua en el caso de personas (hilos) que hacen cola para visitar el baño (recurso compartido). Mientras una persona (hilo) usa el baño facilitándose a sí misma (operación no atómica no constante), él / ella debe asegurarse de que la puerta esté cerrada (exclusión), de lo contrario, podría quedar atrapado en una carga total (comportamiento no deseado) )