Investigación cuantitativa sobre código fuente único
El productor es responsable de generar datos y luego colocarlos en el búfer buf mediante la operación put.
El consumidor es responsable de mostrar datos y leer datos de buf a través de la operación get.
========》
Veamos primero la función principal main()
El productor y el consumidor se implementan mediante dos subprocesos respectivamente. .
La función pthread_create() en la función principal se utiliza para crear estos dos hilos.
Se definen dos variables th_a y th_b para registrar los números de hilo de estos dos hilos.
Los cuerpos de programa del hilo son productores y consumidores respectivamente.
El siguiente pthread_join se utiliza para esperar a que finalicen los dos subprocesos. Porque si no espera, el hilo principal de la función principal finalizará inmediatamente y los dos subprocesos no habrán tenido tiempo de ejecutarse por completo.
=======》
Veamos los dos hilos de productor y consumidor respectivamente.
El productor realiza un bucle cien veces, colocando los datos en el búfer cada vez que llama a put, y finalmente coloca un OVER;
El consumidor realiza un bucle usando get para leer datos del búfer. e Imprimir hasta que se lean más bits de datos que datos.
========》
Veamos la operación de venta y la operación de obtención respectivamente.
Debido a que tanto put como get pueden acceder a buf, buf es un recurso clave. Para abordar este recurso crítico, buf debe bloquearse antes de usarlo.
pthread _ mutex _ lock(b- gt; función para bloquear el semáforo. Cada semáforo solo se puede bloquear una vez (lo que dije puede no ser exacto). Si el semáforo en el parámetro ha estado bloqueado , la función se bloqueará hasta que se desbloquee el semáforo. Esto garantiza que se pueda acceder a los recursos críticos protegidos por el semáforo a través del mutex? >int? BUFFER[BUFFER_SIZE];/*?Este es un búfer circular*/? >
pthread_mutex_t? Lock;/*Este es un semáforo que garantiza la exclusión mutua del acceso al búfer*/ ?
int? writepos/*?Estos dos miembros representan la posición de lectura y la posición de escritura. respectivamente?
notempty/*?Este es un semáforo condicional, lo que indica que el búfer "no está vacío"?
pthread_cond_t?/*?Este es un semáforo condicional, lo que indica que el búfer no está lleno.
};?
Buf es un búfer circular. Veamos primero las posiciones de readpos y writepos cuando el búfer está vacío.
Al cambiar de completo a completo, la siguiente posición de writepos es readpos?
/*?Put es responsable de colocar los datos en el búfer*/. p>¿Invalidar? put(struct? prodcons? *? b, ? int? data)?
{?
//Bloquear el mutex primero
pthread_mutex_lockb-gt; bloquear);?
/*?Aquí se determina si el búfer está lleno y se compara usando writepos 1 y readpos. Consulte la imagen adjunta.
*?Debido a que es un buffer circular, necesitamos tomar el módulo BUFFER_SIZE? .
*?Si el búfer está lleno, esperará un momento hasta que el búfer no esté lleno y luego continuará la ejecución.
*/?
¿Cuándo? ((b- gt; writepos? ?1)??BUFFER_SIZE?==?b- gt; readpos)? {?
printf("¿Esperar? ¿Para qué? ¿No? Completo\n ");?
//Si está lleno, espere a que el consumidor lea los datos y envíe una señal de "no lleno".
pthread_cond_wait(amp;b-gt;no lleno,?ampb-gt;lock);?
}?
/*?Cuando el búfer no está lleno, escribe datos en la ubicación correspondiente a writepos en el búfer*/?
b-gt; buffer; escribirpos]? =?datos;?
//Actualiza writepos a la siguiente posición.
b- gt; escribir pos;?
//Reciclar espacio en el buffer. Si se excede el valor máximo, comience desde el principio.
¿Y si? (b->writepos?gt=?BUFFER_SIZE)? b-gt;writepos? =?0;?
/*?¿Señalar a los consumidores que el buffer no está vacío? */?
pthread_cond_signal(amp;b-gt;notempty);?
//Desbloquear la señal mutex.
pthread_mutex_unlock(&b-gt;bloquear);?
}?
/* - */?
/*?Get es responsable de leer los datos del buffer? */?
int? get(estructura?prodcons?*?b)?
{?
int? datos;?
//Bloquear el semáforo mutex
pthread_mutex_lockb- gt;?
/*? Determine si el búfer está vacío. Si está vacío, espere */?.
¿Cuándo? (b->escribirpos?==?b->readpos)? {?
printf("¿Esperar? ¿Para qué? ¿No? vacío \ n ");?
pthread_cond_wait(&b-gt;notempty,?ampb-gt;lock);?
}?
/*?¿Leer los datos en la posición readpos? */?
¿Datos? =?b- gt;búfer;leer pos];?
//Actualiza readpos a la siguiente posición.
b- gt;leer pos;?
//Recicle el búfer y vuelva a llamar el puntero.
¿Y si? (b->readpos? gt=?BUFFER_SIZE)? b-gt;readpos? =?0;?
/*?Notifique al productor que el búfer no está lleno y que los datos pueden liberarse*/?
pthread_cond_signal(amp;b-gt;no lleno);?
//Desbloquear el semáforo mutex
pthread _ mutex _ unlock(amp; b- gt; lock);?
¿Volver? datos;?
}