Programación del sistema Linux 55 subprocesos: análisis de bloqueos de exclusión mutua

Introducir mutex:

Fallo de competencia entre hilos:

Experimento 1: falla de competencia entre subprocesos, use sleep () para amplificar la falla de competencia

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>


#define THRNUM 20
#define FNAME "/home/mhr/Desktop/xitongbiancheng/parallel/thread/posix/out"
#define LINESIZE 1024 //提前写好1

static void *thr_add(void *p)
{
	FILE *fp;
	char linebuf[LINESIZE];

	fp = fopen(FNAME,"r+");
	if(fp == NULL)
	{
		perror("fopen()");
		exit(1);
	}

	fgets(linebuf,LINESIZE,fp);
	fseek(fp,0,SEEK_SET);

	sleep(1);	
	
	fprintf(fp,"%d\n",atoi(linebuf)+1);
	fclose(fp);
	pthread_exit(NULL);
} 

int main()
{
	pthread_t tid[THRNUM];
	int i,err;

	for(i = 0; i < THRNUM; i++)
	{
		err = pthread_create(tid+i,NULL,thr_add,NULL);
		if(err)
		{
			fprintf(stderr,"pthread_create(): %s\n",strerror(err));
			exit(1);
		}
	}

	for(i = 0;i < THRNUM; i++)
	{
		pthread_join(tid[i],NULL);
	}

	exit(0);
	
}

Debido a que es un solo núcleo de la máquina virtual, el efecto de múltiples núcleos no se puede simular, por lo que dormir (1) en thr_add () durante un segundo se compara con la programación de otros subprocesos por parte del programador, lo que amplifica la competencia entre cada subproceso. y al observar el resultado, se encuentra que se creó. Todos los 20 subprocesos recibieron el archivo FNAME, y el valor que obtuvieron fue 1. Después de dormir (), comenzaron a agregar un valor de escritura, lo que resultó en la escritura repetida de los 2 valor al archivo 20 veces.

La razón de este problema es la competencia entre subprocesos.


Mutex:

Inserte la descripción de la imagen aquí

¡La oración con líneas rojas es demasiado importante! ! ! Una vez que el mutex está bloqueado, cualquier otro hilo que intente bloquear el mutex nuevamente será bloqueado hasta que el hilo actual libere el mutex,
incluso si quiere retener el bloqueo nuevamente sin desbloquearlo. ! !

NAME
       pthread_mutex_destroy, pthread_mutex_init — destroy and initialize a mutex,初始化和销毁 一个 互斥量

SYNOPSIS
       #include <pthread.h>


SYNOPSIS
       #include <pthread.h>
       
	 //销毁
       int pthread_mutex_destroy(pthread_mutex_t *mutex);

//动态初始化
       int pthread_mutex_init(pthread_mutex_t *restrict mutex,
           const pthread_mutexattr_t *restrict attr);

//静态初始化方式
       pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

Bloquear y desbloquear el mutex:

Inserte la descripción de la imagen aquí

NOMBRE
pthread_mutex_lock, pthread_mutex_trylock, pthread_mutex_unlock - bloquear y desbloquear un mutex

SINOPSIS
#include <pthread.h>

	//以阻塞的方式 限制住某段代码的执行
   int pthread_mutex_lock(pthread_mutex_t *mutex);
   
   //以非阻塞的方式 限制住某段代码的执行
   int pthread_mutex_trylock(pthread_mutex_t *mutex);

	//解锁
   int pthread_mutex_unlock(pthread_mutex_t *mutex); 

Malentendido:
No entienda directamente que mientras haya una declaración pthread_mutex_lock (), el siguiente código es una sección crítica, por lo que es fácil confundirse. Pero debe entenderse como: solo quiero obtener el bloqueo, luego, cuando otros subprocesos quieran el bloqueo, no pueden obtener el bloqueo y se bloquearán. Utilice esta regla para crear la zona crítica que necesitamos.

Experimento 2: modifique el experimento anterior para asegurarse de que el código que solo puede realizar una persona al mismo tiempo sea la sección crítica.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>


#define THRNUM 20
#define FNAME "/home/mhr/Desktop/xitongbiancheng/parallel/thread/posix/out"
#define LINESIZE 1024

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

static void *thr_add(void *p)
{
	FILE *fp;
	char linebuf[LINESIZE];

	fp = fopen(FNAME,"r+");
	if(fp == NULL)
	{
		perror("fopen()");
		exit(1);
	}

pthread_mutex_lock(&mut); //上锁

	fgets(linebuf,LINESIZE,fp);
	fseek(fp,0,SEEK_SET);

	//sleep(1);	
	
	fprintf(fp,"%d\n",atoi(linebuf)+1); // 全缓冲,需要fflush 或者 fclose 刷新 才能写到目标文件
	fclose(fp);// fprintf(fp  全缓冲,需要fflush 或者 fclose 刷新 才能写到目标文件,所以也在临界区

pthread_mutex_unlock(&mut); //解锁

	pthread_exit(NULL);
} 

int main()
{
	pthread_t tid[THRNUM];
	int i,err;

	for(i = 0; i < THRNUM; i++)
	{
		err = pthread_create(tid+i,NULL,thr_add,NULL);
		if(err)
		{
			fprintf(stderr,"pthread_create(): %s\n",strerror(err));
			exit(1);
		}
	}

	for(i = 0;i < THRNUM; i++)
	{
		pthread_join(tid[i],NULL);
	}

	pthread_mutex_destroy(&mut);
	exit(0);
	
}




mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ gcc add.c -lpthread
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ cat out 
1
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ ./a.out 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ cat out 
21
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ ./a.out 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ cat out 
41
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ ./a.out 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ cat out 
61
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 

Experimento 3, exclusión mutua, profundice su comprensión: los cuatro subprocesos envían continuamente a, b, c, d al terminal en secuencia dentro del tiempo especificado, y cada subproceso genera una letra

Cree cuatro mutex, cuatro subprocesos, en el código de la sección crítica, cada subproceso es responsable de mantener el bloqueo, generar y liberar el bloqueo del siguiente subproceso. De esta manera, cada hilo puede sondear la salida del bloqueo.

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

#define THRNUM 4

static pthread_mutex_t mut[THRNUM];

static int next(int n)
{
	if(n+1 == THRNUM)
		return 0;
	return n+1;

}

static void *thr_add(void *p)
{
	int n = (int)p;
	int c = 'a' + (int)p;
	while(1)
	{
		pthread_mutex_lock(mut+n);
		write(1,&c,1);
		pthread_mutex_unlock(mut+next(n));//这里会执行 被阻塞的目标线程,当前线程由于没有释放自己持有的锁,会被再次阻塞。
	}
		

	pthread_exit(NULL);
} 

int main()
{
	pthread_t tid[THRNUM];
	int i,err;

	for(i = 0; i < THRNUM; i++)
	{
	
		pthread_mutex_init(mut+i,NULL);
		pthread_mutex_lock(mut+i);

		err = pthread_create(tid+i,NULL,thr_add,(void *)i);
		if(err)
		{
			fprintf(stderr,"pthread_create(): %s\n",strerror(err));
			exit(1);
		}
	}

	pthread_mutex_unlock(mut+0);//释放线程1的锁

	alarm(5);

	for(i = 0;i < THRNUM; i++)
	{
		pthread_join(tid[i],NULL);
	}

	exit(0);
	
}

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/LinuxArmbiggod/article/details/114264585
Recomendado
Clasificación