[Mutex y semáforo] Comunicación de subprocesos: mutex y semáforo

Tabla de contenido

0. Cerraduras Mutex y semáforos

Descripción general de Mutex síncrono

1. Bloqueo mutex

1.1 El concepto de bloqueo mutex

1.2 Inicialización del bloqueo Mutex: función pthread_mutex_init

1.3 Bloqueo mutex: función pthread_mutex_lock

1.4 Desbloqueo Mutex: función pthread_mutex_unlock

1.5 Destruir el bloqueo mutex: función pthread_mutex_destroy

1.6 Caja de cerradura Mutex

1.61 Consecuencias de no utilizar bloqueos mutex

 1.62 Resultados del uso de bloqueos mutex 

2. Cantidad de señal

2.1 El concepto de semáforo

2.2 Inicialización del semáforo: función sem_init

2.3 Operación P del semáforo: función sem_wait

Operación de 2,4 V del semáforo: función sem_post

2.5 Obtener el valor de conteo del semáforo: función sem_getvalue

2.6 Destrucción de semáforo: función sem_destroy

2.7 Uso de semáforos

2.7.1 Semaphore implementa la función de exclusión mutua

2.7.2 Semaphore realiza la función de sincronización

 Resumir:


0. Cerraduras Mutex y semáforos

Descripción general de Mutex síncrono

        En un sistema operativo multitarea, es posible que varias tareas que se ejecutan simultáneamente deban acceder o utilizar el mismo recurso. Existen dependencias entre múltiples tareas y la operación de una tarea depende de otra.

        La sincronización y la exclusión mutua se utilizan para resolver estos dos problemas.

Mutuamente excluyentes:

        Un recurso público solo puede ser utilizado por un proceso o subproceso a la vez, y varios procesos o subprocesos no pueden utilizar recursos públicos al mismo tiempo. Hay dos métodos principales para la sincronización y exclusión mutua de procesos y subprocesos en el estándar POSIX: semáforos y bloqueos mutex.

Sincronizar:

        Dos o más procesos o subprocesos se sincronizan durante la operación y se ejecutan en un orden predeterminado.

        La sincronización es un orden basado en la exclusión mutua.

1. Bloqueo mutex

1.1 El concepto de bloqueo mutex

        Mutex es un método de bloqueo simple para controlar el acceso a recursos compartidos. Mutex tiene solo dos estados, a saber, bloquear y desbloquear. Antes de acceder a este recurso, primero debe solicitar un mutex.

  •         Si el mutex está en estado desbloqueado, el mutex se solicitará y bloqueará inmediatamente.
  •         Si el mutex está en estado de bloqueo, el solicitante está bloqueado de forma predeterminada. La operación de desbloqueo debe ser realizada por el casillero.

Inicialice el bloqueo mutex: función pthread_mutex_init.

        Mutex está representado por el tipo de datos pthread_mutex_t y debe inicializarse antes de utilizar el bloqueo mutex.

Bloqueo mutex asignado estático:

        pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

Asignar dinámicamente bloqueo mutex:

        pthread_mutex_t exclusión mutua;

Destruya el bloqueo mutex: pthread_mutex_destroy

1.2 Inicialización del bloqueo Mutex: función pthread_mutex_init

Función pthread_mutex_init:

#incluir<pthread.h>

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

Función:

        Inicialice un bloqueo mutex.

parámetro:

        mutex: la dirección del bloqueo mutex.

        attr: atributo del bloqueo mutex, NULL es el atributo predeterminado.

valor de retorno:

        Éxito: 0

        Fallo: no 0

1.3 Bloqueo mutex: función pthread_mutex_lock

función pthread_mutex_lock

#incluir<pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);

Función:

        Bloquear el mutex. Si ya está bloqueado, la persona que llama bloquea hasta que se desbloquee el mutex.

parámetro:

        mutex: el bloqueo mutex especificado.

valor de retorno:

        Éxito: 0

        Fallo: no 0

#incluir<pthread.h>

int pthread_mutex_trylock(pthread_mutex_t * mutex);

Función:

        Bloquee el mutex. Si ya está bloqueado, el bloqueo falla y la función regresa inmediatamente.

parámetro:

        mutex: dirección de bloqueo mutex.

valor de retorno:

        Éxito: 0

        Fallo: no 0 

1.4 Desbloqueo Mutex: función pthread_mutex_unlock

función pthread_mutex_unlock

#incluir<pthread.h>

int pthread_mutex_unlock(pthread_mutex_t *mutex);

Función:

        Desbloquea el mutex especificado.

parámetro:

        mutex: dirección de bloqueo mutex.

valor de retorno:

        Éxito: 0

        Fallo: no 0

1.5 Destruir el bloqueo mutex: función pthread_mutex_destroy

función pthread_mutex_destroy

#incluir<pthread.h>

int pthread_mutex_destroy(pthread_mutex_t *mutex);

Función:

        Destruye el bloqueo mutex especificado.

parámetro:

        mutex: dirección de bloqueo mutex.

valor de retorno:

        Éxito: 0

        Fallo: no 0

1.6 Caja de cerradura Mutex

1.61 Consecuencias de no utilizar bloqueos mutex
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>

int money = 10000;

void* pthread_fun1(void* arg)
{
    int get, yu, shiji;
    get = 10000;

    printf("zhangsan look balance\n");
    sleep(1);
    yu = money;

    printf("zhangsan spent money\n");
    sleep(1);
    if (get > yu)
    {
        shiji = 0;

    }
    else
    {
        shiji = get;
        yu = yu - get;
        money = yu;
    }
    printf("zhangsan want spent %d, fact spent is %d, balance is %d\n", get, shiji, yu);
    pthread_exit(NULL);
}
void* pthread_fun2(void* arg)
{
    int get, yu, shiji;
    get = 10000;

    printf("lisi look balance\n");
    sleep(1);
    yu = money;

    printf("lisi spent money\n");
    sleep(1);
    if (get > yu)
    {
        shiji = 0;

    }
    else
    {
        shiji = get;
        yu = yu - get;
        money = yu;
    }
    printf("lisi want spent %d, fact spent is %d, balance is %d\n", get, shiji, yu);
    pthread_exit(NULL);
}
int main()
{

    pthread_t thread1, thread2;

    if (pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0)
    {
        perror("fail to pthread_create");
        exit(1);
    }
    if (pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0)
    {
        perror("fail to pthread_creat");
        exit(1);
    }

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    return 0;
}

Captura de pantalla de ejecución:

 1.62 Resultados del uso de bloqueos mutex 

Ejemplo de código:

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

int money = 10000;
//第一步:创建互斥锁
pthread_mutex_t mutex;

void* pthread_fun1(void* arg)
{
    int get, yu, shiji;
    get = 10000;
    //第三步,互斥锁上锁
    pthread_mutex_lock(&mutex);
    printf("zhangsan look balance\n");
    sleep(1);
    yu = money;

    printf("zhangsan spent money\n");
    sleep(1);
    if (get > yu)
    {
        shiji = 0;

    }
    else
    {
        shiji = get;
        yu = yu - get;
        money = yu;
    }
    printf("zhangsan want spent %d, fact spent is %d, balance is %d\n", get, shiji, yu);
    //第四步,互斥锁解锁
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
void* pthread_fun2(void* arg)
{
    int get, yu, shiji;
    get = 10000;
    //第三步,互斥锁上锁
    pthread_mutex_lock(&mutex);
    printf("lisi look balance\n");
    sleep(1);
    yu = money;

    printf("lisi spent money\n");
    sleep(1);
    if (get > yu)
    {
        shiji = 0;

    }
    else
    {
        shiji = get;
        yu = yu - get;
        money = yu;
    }
    printf("lisi want spent %d, fact spent is %d, balance is %d\n", get, shiji, yu);
    //第四步,互斥锁解锁
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
int main()
{
    //第二步,初始化互斥锁
    pthread_mutex_init(&mutex, NULL);
    pthread_t thread1, thread2;

    if (pthread_create(&thread1, NULL, pthread_fun1, NULL) != 0)
    {
        perror("fail to pthread_create");
        exit(1);
    }
    if (pthread_create(&thread2, NULL, pthread_fun2, NULL) != 0)
    {
        perror("fail to pthread_creat");
        exit(1);
    }

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    //第五步,销毁互斥锁
    pthread_mutex_destroy(&mutex);
    return 0;
}

Resultados de:

2. Cantidad de señal

2.1 El concepto de semáforo

        Los semáforos se utilizan ampliamente para la sincronización y exclusión mutua entre procesos o subprocesos. Un semáforo es esencialmente un contador de enteros no negativos, que se utiliza para controlar el acceso a recursos públicos.

        Al programar, puede determinar si tiene permiso de acceso al recurso público en función del resultado de operar el valor del semáforo. Cuando el valor del semáforo es mayor que 0, puede acceder a él; de lo contrario, se bloqueará.

        El semáforo también se llama operación PV. PV es la operación en el semáforo. Una operación P reduce el semáforo sem en 1 y una operación V hace que el semáforo sem+1. Para la operación P, si el valor sem del semáforo es menor o igual a 0, se bloqueará la operación P. Si el valor del semáforo es mayor que 0, la operación P se puede realizar para restar 1.

Los semáforos se utilizan principalmente en dos situaciones típicas: sincronización y exclusión mutua entre procesos o subprocesos.

  • Si se utiliza para exclusión mutua, varios procesos (o subprocesos) a menudo solo establecen un semáforo.
  • Si se usa para operaciones de sincronización, a menudo se configuran múltiples semáforos y se organizan diferentes valores iniciales para lograr la secuencia de ejecución entre ellos.

Los semáforos se utilizan para exclusión mutua:

Los semáforos se utilizan para la sincronización:

 

2.2 Inicialización del semáforo: función sem_init

función sem_init

#incluir<semaforo.h>

int sem_init(sem_t *sem, int pshared, valor int sin signo);

Función:

        Crea un semáforo e inicializa su valor.

parámetro:

        sem: La dirección del semáforo.

        pshared: igual a 0, el semáforo se comparte entre subprocesos; distinto de 0, el semáforo se comparte entre procesos.

        valor: El valor inicial del semáforo.

valor de retorno:

        Éxito: 0

        Fallo: -1

2.3 Operación P del semáforo: función sem_wait

función sem_wait

#incluir<semaforo.h>

int sem_wait(sem_t *sem);

Función:

        Disminuya el valor del semáforo en 1. Si el valor del semáforo es menor o igual a 0, esta función hará que la persona que llama se bloquee.

parámetro:

        sem: La dirección del semáforo.

valor de retorno:

        Éxito: 0

        Fallo: -1

#incluir<semaforo.h>

int sem_trywait(sem_t *sem);

Función:

        Disminuya el valor del semáforo en 1. Si el valor del semáforo es menor que 0, la operación en el semáforo falla y la función regresa inmediatamente.

parámetro:

        sem: dirección del semáforo.

valor de retorno:

        Éxito: 0

        Fallo: -1

Operación de 2,4 V del semáforo: función sem_post

función sem_post

#incluir<semaforo.h>

int sem_post(sem_t *sem);

Función:

        Aumente el valor del semáforo en 1 y envíe una señal para despertar el hilo en espera.

parámetro:

        sem: dirección del semáforo.

valor de retorno:

        Éxito: 0

        Fallo: -1 

2.5 Obtener el valor de conteo del semáforo: función sem_getvalue

función sem_getvalue

#incluir<semaforo.h>

int sem_getvalue(sem_t *sem, int *sval);

Función:

        Obtenga el valor del semáforo identificado por sem y guárdelo en sval.

parámetro:

        sem: dirección del semáforo.

        sval: la dirección donde se guarda el valor del semáforo.

valor de retorno:

        Éxito: 0

        Fallo: -1

2.6 Destrucción de semáforo: función sem_destroy

función sem_destroy

#incluir<semaforo.h>

int sem_destroy(sem_t *sem);

Función:        

        Elimina el semáforo identificado por sem.

parámetro:

        sem: dirección del semáforo.

valor de retorno:

        Éxito: 0

        Fallo: -1

2.7 Uso de semáforos

2.7.1 Semaphore implementa la función de exclusión mutua

Ejemplo de código:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>

//第一步,创建信号量
sem_t sem;

void printer(char* str)
{
    //第三步,P操作
    sem_wait(&sem);
    while (*str)
    {
        putchar(*str);
        fflush(stdout);
        str++;
        sleep(1);
    }
    //第四步,V操作
    sem_post(&sem);
}

void* thread_fun1(void* arg)
{
    char* str1 = "hello";
    printer(str1);
}
void* thread_fun2(void* arg)
{
    char* str2 = "world";
    printer(str2);
}

int main()
{
    //第二步,初始化信号量
    sem_init(&sem, 0, 1);
    pthread_t tid1, tid2;

    pthread_create(&tid1, NULL, thread_fun1, NULL);
    pthread_create(&tid2, NULL, thread_fun2, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    printf("\n");
    //第五步,销毁信号量
    sem_destroy(&sem);
    return 0;
}

Captura de pantalla de ejecución:

2.7.2 Semaphore realiza la función de sincronización

Ejemplo de código:

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

char ch = 'a';
//第一步,创建两个信号量
sem_t sem_g, sem_p;

void* pthread_g(void* arg)
{
    while (ch <= 'z')
    {
        //第四步,后执行线程
        sem_wait(&sem_g);
        ch++;
        sleep(1);
        //第六步,V操作
        sem_post(&sem_p);
    }
}

void* pthread_p(void* arg)
{
    while (ch < 'z')
    {
        //第三步,先执行线程
        sem_wait(&sem_p);
        printf("%c", ch);
        fflush(stdout);
        //第五步,V操作
        sem_post(&sem_g);
    }
}
int main()
{
    //第二步,初始化信号量
    sem_init(&sem_g, 0, 0);
    sem_init(&sem_p, 0, 1);
    pthread_t tid1, tid2;

    pthread_create(&tid1, NULL, pthread_g, NULL);
    pthread_create(&tid2, NULL, pthread_p, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    printf("\n");
    //第七步,销毁信号量
    sem_destroy(&sem_g);
    sem_destroy(&sem_p);
    return 0;
}

Captura de pantalla de ejecución:

 Resumir:

        En general, los mutex y los semáforos son herramientas importantes para la sincronización de procesos y subprocesos. Los bloqueos Mutex se utilizan principalmente para proteger recursos y garantizar que solo un subproceso o proceso acceda a un determinado recurso al mismo tiempo, evitando así problemas de concurrencia. Los semáforos se utilizan más para la comunicación y sincronización entre subprocesos y procesos, controlan el acceso concurrente dentro de un cierto rango y proporcionan un control de concurrencia más detallado para los programas.

        Dominar el uso y las diferencias de mutex y semáforos puede mejorar en gran medida la eficiencia y la estabilidad de la programación multiproceso y multiproceso.

Supongo que te gusta

Origin blog.csdn.net/crr411422/article/details/131421923
Recomendado
Clasificación