Sistemas Distribuidos
Proceso y Comunicación con
Hilos
René Guamán-Quinche
Facultad de la Energía, las Industrias y los Recursos Naturales No Renovables
Carrera de Ingeniería en Sistemas/Computación
Noviembre, 2020
Loja, Ecuador
2
1. Procesos
2. Hilos
3. Posix
4. Hilos y concurrencia
Contenido
3
Objetivo
Comprender los diferentes conceptos relacionados con los procesos y la
comunicación distribuidos como la base para el desarrollo de
aplicaciones distribuidas.
4
Proceso
 Programa: fichero con comandos (Estáticos)
 Proceso: Abstracción de un programa en ejecución (Dinámico)
 La CPU es un recurso importantísimo
 Mas procesos que CPUs → ¿Qué procesos la usa?
 Ocurre igual con otros recurso ilimitados (ej. memoria)
 Multiprogramación: La CPU pasa de un proceso a otro rápidamente dándole a
cada uno un pequeño tiempo de computación
 → pseudo-paralelismo
 → cambio de contexto
 → algoritmos de planificación
 Multiprocesador → Verdadero paralelismo
5
Proceso
 Definición
 Programa en ejecución
 Unidad de procesamiento gestionada por el SO
 Para que un programa pueda ser ejecutado ha de residir en memoria principal
 Árbol de procesos
 Relación de jerarquías
6
Proceso
El sistema operativo mantiene un conjunto de estructuras de información que
permiten identificar y gestionar los procesos
7
Proceso monothread o multithread
 Un SO de multiprocesamiento se puede ejecutar varios procesos al mismo tiempo
 Cada proceso se caracteriza por ser autónomo y una identidad indenpendiente y
tienen su propio espacio de memoria
 SO tiene un scheduler o planificador, el que decide cual proceso puede utilizar la CPU
en un momento dado
 En sistemas uni-procesador solo un proceso puede a la vez
 Una característica de los procesos es que no comparten nada, son procesos separados
shared nothing
 Debe haber servicios en el SO que permitan compartir memoria
 Aplicaciones múltiples hilos tiene varios puntos de ejecución o varios caminos o rutas en
las cuales se pueden ejecutar las aplicaciones
 Cada puntos de ejecución es llamado hilo
 Los hilos comparten memoria
8
Proceso monothread o multithread
 Existen aplicaciones de un sólo hilo o hilo de ejecución
 Si una aplicación tiene muchas tareas por ejecutar, solo una tarea se puede ejecutar a la
vez
 La tareas requieren mucho procesamiento puede parecer que la aplicación se ha
congelado o no responde
 Aplicaciones Multitheaded cada tarea esta ejecutada por un hilo
 Permite que las aplicaciones sean más modulares donde cada tarea está en una tarea, y
cada modulo está ejecudo por un hilo
 Ejemplos:
 Editor de documentos
 Manejador de ventanas
9
Proceso monothread o multithread
 Un proceso ligero, hilo o thread es un programa en ejecución (flujo de ejecución) que
comparte la imagen de memoria (y otras informaciones) con otros procesos ligeros
 Dependiendo del número de procesos que puedan ejecutar simultáneamente, un SO es
monotarea o multitarea
 Un proceso ligero puede contener un solo flujo de ejecución (monothread) o más
(multithread)
 Por ejemplo, en el lenguaje C el hilo de ejecución primario se corresponde con la
función principal main
10
Hilo
Información propia/compartida
 Por thread (información propia)
 Contador de programa, Registros
 Pila
 Estado (ejecutando, listo o bloqueado)
 Por proceso (información compartida)
 Espacio de memoria
 Variables globales
 Ficheros abiertos
 Procesos hijos
 Temporizadores
 Señales y semáforos
 Contabilidad
11
Hilo
Estructura de un proceso con threads
12
Hilo
Estructura de un proceso con threads
 Cada hilo tiene su propio contexto, ej.
registros, y las llamadas a pila
 Quien selecciona el siguiente hilo a
ejecutar
 SO scheduleder
 Procesos de usuario a ejecutar
 Los programadores no pueden hacer
ninguna presunción respecto a cómo
los hilos son planificados, es aleatorio
 Los SO, plataformas tienen sus
propias políticas de planificación
13
Hilo
 Como los procesos convencionales, un proceso ligero puede estar en varias situaciones o
estados: ejecutando, listo o bloqueado
 El estado del proceso será la combinación de los estados de sus procesos ligeros
Estados del proceso ligero
14
Hilo
Threads y paralelismo
 Los procesos ligeros permiten paralelizar una aplicación
 Un programa puede dividirse en procedimientos que pueden ejecutar de manera
independiente mediante procesos ligeros
 Los procesos ligeros pueden lanzar su ejecución de manera simultánea
 Diseño modular de la aplicación
 La base del paralelismo:
 Mantener algún proceso ligero siempre en estado de ejecución: “mientras que un proceso
está bloqueado otro podría estar ejecutando”
15
Hilo
Ejecución serie vs. paralela
16
Hilo
Threads take advantage of multi-core systems
17
Posix
Posix Threds
 Posix – Portable Operating System Interface
 Define rutinas
 Creación
 Barrera sobre los hilos, puntos de sincronización
 Otros
 Matar
 Inpeccionar características de los hilos
18
Posix
 Pthreads es la implementacipon de Posix thereads
 Linux, Mac y Windows
 Todos los programas que usen pthreads requiren incluir el archivo de
cabecera pthread.h
 Para compiar un programa en phtread
 gcc pthread demo.c -o demo
19
Posix
Crear un thread:
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void * (*funcion)(void *),
void * arg);
donde:
thread Identificador del nuevo thread (se captura cuando se crea)
attr Atributos a aplicar al nuevo thread o NULL
funcion Función a ejecutar por el thread que es creado
arg Puntero a el/los argumentos del thread
devuelve:
int 0 si éxito o -1 si error
Obtener el identificador de un thread:
pthread_t pthread_self(void);
20
Posix
Atributos de un proceso ligero:
 Un hilo se crea con una serie de atributos por defecto
 Ejemplo: Por defecto, un hilo es joinable o No Independiente
 Es posible modificar los atributos por defecto del hilo:
 Inicia un objeto atributo que se puede utilizar para crear nuevos procesos ligeros
 int pthread_attr_init(pthread_attr_t *attr);
 Destruye un objeto de tipo atributo
 int pthread_attr_destroy(pthread_attr_t *attr);
 Cambiar el estado de terminación (Joinable / Detached)
int pthread_attr_setdetachstate( pthread_attr_t *a, int detachstate);
Si detachstate es
 PTHREAD_CREATE_DETACHED el proceso se crea independiente
 PTHREAD_CREATE_JOINABLE el proceso se crea no independiente
 Otras atributos: tamaño de pila, planificación, prioridad, etc.
21
Posix
Terminación de procesos ligeros
 Finaliza la ejecución del proceso ligero:
int pthread_exit(void *value);
 Para procesos creados como NO independientes es además necesario:
int pthread_join(pthread_t thid, void **value);
 pthread_t: identificador del hilo que se espere que termine
 **value: se va almacenar el resultado de algunos valores que devuelva el hilo al
terminar
 Espera la terminación del proceso con identificador thid
 Devuelve en el segundo argumento el valor pasado en pthread_exit.
 Sólo se puede esperar la terminación de procesos ligeros no
 independientes (PTHREAD_CREATE_JOINABLE)
22
Ejemplos
Práctica 1: Threads
#include <pthread.h>
#include <stdio.h>
#define MAX 100
void *inc_x(void *x_void_ptr);
int main(){
int x = 0;
int y = 0;
printf("x: %d, y: %dn", x, y);
pthread_t inc_x_thread;
if (pthread_create(&inc_x_thread, NULL, inc_x, &x)){
fprintf(stderr, "Error creating threadn");
return 2;
}
while (++y <MAX);
printf("y increment finishedn");
printf("X: %d, y: %dn", x, y);
return 0;
}
void *inc_x(void *x_void_ptr){
printf("I am in methodn");
int *x_ptr = (int *)x_void_ptr;
while (++(*x_ptr) < MAX);
printf("x increment finishedn");
return NULL;
}
hilo1_posix.cpp
23
Ejemplos
Práctica 1: Threads
hilo1_posix.cpp
¿Porqué x = 0?
24
Ejemplos
Práctica 1: Threads
¿Porqué x = 0?
Porque en el primer ejemplo el programa no espera el hilo que termine su ejecución
¿Cómo hacemos que programa espere al hilo?
25
Ejemplos
Práctica 2: Threads hilo2_posix.cpp
Agregar la función pthread_join para que el programa espere hasta que hilo
termine su ejecución
if(pthread_join(inc_x_thread, NULL)){
fprintf(stderr, "Error joining threadn");
return 2;
}
26
Ejemplos
Práctica 2: Threads hilo2_posix.cpp
#include <pthread.h>
#include <stdio.h>
#define MAX 100
void *inc_x(void *x_void_ptr);
int main(){
int x = 0;
int y = 0;
printf("x: %d, y: %dn", x, y);
pthread_t inc_x_thread;
if (pthread_create(&inc_x_thread, NULL, inc_x,
&x)){
fprintf(stderr, "Error creating threadn");
return 2;
}
while (++y <MAX);
printf("y increment finishedn");
// esperamos al a todos los hilos
if(pthread_join(inc_x_thread,NULL)){
fprintf(stderr, "Error joining
threadn");
return 2;
}
printf("X: %d, y: %dn", x, y);
return 0;
}
void *inc_x(void *x_void_ptr){
printf("I am in methodn");
int *x_ptr = (int *)x_void_ptr;
while (++(*x_ptr) < MAX);
printf("x increment finishedn");
return NULL;
}
27
Ejemplos
Práctica 2: Threads hilo2_posix.cpp
El tiempo de ejecución incrementa porque el programa ahora espera al hilo hasta que termine
28
Hilos y concurrencia
Se tiene un vector de 15 elementos, se quiere buscar cuantas veces se repite 3
La complejidad del problema es O(n), porque se a ir comparando elemento por
elemento y si se encontra un número 3 se va incrementando un contador
for (i = 0; i > len(vector); i++)
if (vector [ i ] == 3)
count++
29
Hilos y concurrencia
Threads and concurrency programa.cpp – hilo secuencial
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define VECTOR_SIZE 100000000
// variables globales
int *array;
int count = 0;
int double_count = 0;
void initialize_vector(){
int i = 0;
array = (int*) malloc(sizeof(int) * VECTOR_SIZE);
if(array == NULL){
printf("Memoria no disponiblen");
exit(-1);
}
for(;i < VECTOR_SIZE; i++){
array[i] = rand() % 20;
if (array[i] == 3)
double_count++;
}
}
void count_3s(){
int i = 0;
for(;i < VECTOR_SIZE; i++){
if (array[i] == 3)
count++;
}
}
30
Hilos y concurrencia
Threads and concurrency programa.cpp – hilo secuencial
int main(int argc, char* argv[]){
int i = 0;
int err;
clock_t t1, t2;
printf("Running 3s-00");
srand(time(NULL));
printf("*** 3s-00 ***n");
printf("Initializing vector.... ");
fflush(stdout);
initialize_vector();
printf("Vector initialized! n");
fflush(stdout);
t1 = clock();
count_3s();
t2 = clock();
printf("Count by thread %d!n",count);
printf("Double check %d!n",double_count);
printf("[[3s-00] tiempo transcurrido %fn",(((float)t2 - (float)t1) /1000000.0F) * 1000);
printf("Finishing 3s-00");
return 0;
}
31
Hilos y concurrencia
Threads and concurrency hilo3_posix.cpp – hilo secuencial
32
Hilos y concurrencia
hilo1_posix.cpp – hilo concurrente
33
Hilos y concurrencia
Threads and concurrency
hilo1_posix.cpp – hilo concurrente
#define MAX_THREADS 8
int *array;
int length = VECTOR_SIZE;
int count = 0;
int double_count = 0;
// main ………….
while(i < max_threads){
err = pthread_create(&tid[i], NULL, &count3s_thread, (void*)i);
if (err != 0)
printf("[3s-01] Can't create a thread [%ld]n",i);
else
printf("[3s-01] Thread created [%ld]n", i);
i++;
}
34
Hilos y concurrencia
Threads and concurrency
hilo1_posix.cpp – hilo concurrente
#define MAX_THREADS 8
int *array;
int length = VECTOR_SIZE;
int count = 0;
int double_count = 0;
void *count3s_thread(void *arg){
int i;
int length_per_thread = length / max_threads;
long id = (long)arg;
int start = id * length_per_thread;
printf("nThread [%ld] starts [%d] length [%d]n", id, start,
length_per_thread);
for(i = start; i < start + length_per_thread; i++){
if (array[i] == 3){
count++;
}
}
}
35
Hilos y concurrencia
Threads and concurrency
hilo1_posix.cpp – hilo concurrente
Los count y double_count no son
iguales
Desface en lo que cuentan los
hilos y la cuenta total
36
Hilos y concurrencia
Threads and concurrency
hilo1_posix.cpp – hilo concurrente
37
Hilos y concurrencia
hilo2_posix.cpp – hilo concurrente
for(; i < max_threads; i++){
void *status;
int rc;
rc = pthread_join(tid[i],&status);
if(rc){
printf("ERROR; return code from pthread() is %d
n", rc);
exit(-1);
}else{
printf("Thread [%ld] exited with status [%ld] n", i,
(long)status);
}
}
La aplicación principal debería esperar a los hilos que se crearon
38
Hilos y concurrencia
hilo2_posix.cpp – hilo concurrente
Tanto el count y el doube check no tienen
el mismo valor
Problemas de Concurrencia
39
Hilos y concurrencia
Problemas de Concurrencia
El count es la variable común
Tanto el hilo A y el hilo B
acceden a una variables común
¿Cómo podemos resolver ese
error?
40
Hilos y concurrencia
Problemas de Concurrencia
Usar candados
Hilo A lee count y le pone un
candado para que ningún hilo
pueda escribir en esa variable
por otro hilo
Se vuelve un algoritmo
secuencial al acceso a datos
41
Hilos y concurrencia
pthread_mutex_t mutex;
………………………..
pthread_mutex_lock(&mutex); // se llama esta sección
crítica
for(i = start; i < start + length_per_thread; i++){
if (array[i] == 3){
count++;
}
}
pthread_mutex_unlock(&mutex);
……………………
//El candado que evita la concurrencia
pthread_mutex_init(&mutex, NULL);
pthread_mutex_destroy(&mutex);
 Existe una nueva variable t_mutex que
es un candado a traves pthread_mutex
 En count3s_thread, cuando un hilo
comienza a contar pone un candado
sobre esa región de memoria donde se
va a modificar cont, esta parte del
código se le llama sección crítica
 Inicialización el candado (mutex), la
variable mutex a sido inicializada de
forma global, todos los hilos la podrán
ver
42
Hilos y concurrencia
Threads and concurrency
43
Hilos y concurrencia
El problema de la sección crítica
 Sistema compuesto por n procesos
 Cada uno tiene un fragmento de código: sección crítica
 Los procesos deben acceder a la SC con exclusividad
 Estructura general de cualquier mecanismo utilizado para resolver el problema de la
sección crítica:
 Requisitos que debe ofrecer cualquier solución para resolver el problema
 de la sección crítica:
 Exclusión mutua
 Progreso
 Espera limitada
Entrada en la sección crítica
Código de la sección crítica
Salida de la sección crítica
44
Hilos y concurrencia
//pthread_mutex_lock(&mutex);
for(i = start; i < start + length_per_thread;
i++){
if (array[i] == 3){
pthread_mutex_lock(&mutex);
count++;
pthread_mutex_unlock(&mutex);
}
}
//pthread_mutex_unlock(&mutex);
¿Qué sucede si se usa el bloqueo alrededor de declaraciones de código donde se
modifica la variable compartida?
45
Hilos y concurrencia
46
Hilos y concurrencia
47
Hilos y concurrencia
// Definición de contadores privados para cada hilo
int private_count[MAX_THREADS];
**************************************
for(i = start; i < start + length_per_thread; i++){
if (array[i] == 3){
private_count[id]++; // cambia
}
}
// cambia... sección crítica
pthread_mutex_lock(&mutex);
count = count + private_count[id];
pthread_mutex_unlock(&mutex);
Se crea un arreglo de variables privadas
count
Cada hilo recorre el segmento que le
corresponde y podra contar con su
contador y bloquea el count fuera del for
48
Hilos y concurrencia
49
Cŕeditos
• Transparencias basadas por:
• Coulouris Dollimore, Distributed Systems: Concepts and Design
https://ce.guilan.ac.ir/images/other/soft/distribdystems.pdf
• García-Carballeira F., Tema 3 Comunicación y sincronización entre
procesos http://ocw.uc3m.es/ingenieria-informatica/sistemas-
distribuidos-2013/Tema3_ComunicacionYsincronizacion.pdf/view
• Sanabria, John, Sistemas Distribuidos – Hilos – Prácticas,
https://www.youtube.com/playlist?list=PLNqsgMwXL3mFmd8X8Fgv
Z_6ljjzucIDbN
Networking académico:
Correo electrónico: rguaman@unl.edu.ec
Twitter: @rene5254
SlideShare: https://es.slideshare.net/rene5254
50
Gracias

Hilos con Posix

  • 1.
    Sistemas Distribuidos Proceso yComunicación con Hilos René Guamán-Quinche Facultad de la Energía, las Industrias y los Recursos Naturales No Renovables Carrera de Ingeniería en Sistemas/Computación Noviembre, 2020 Loja, Ecuador
  • 2.
    2 1. Procesos 2. Hilos 3.Posix 4. Hilos y concurrencia Contenido
  • 3.
    3 Objetivo Comprender los diferentesconceptos relacionados con los procesos y la comunicación distribuidos como la base para el desarrollo de aplicaciones distribuidas.
  • 4.
    4 Proceso  Programa: ficherocon comandos (Estáticos)  Proceso: Abstracción de un programa en ejecución (Dinámico)  La CPU es un recurso importantísimo  Mas procesos que CPUs → ¿Qué procesos la usa?  Ocurre igual con otros recurso ilimitados (ej. memoria)  Multiprogramación: La CPU pasa de un proceso a otro rápidamente dándole a cada uno un pequeño tiempo de computación  → pseudo-paralelismo  → cambio de contexto  → algoritmos de planificación  Multiprocesador → Verdadero paralelismo
  • 5.
    5 Proceso  Definición  Programaen ejecución  Unidad de procesamiento gestionada por el SO  Para que un programa pueda ser ejecutado ha de residir en memoria principal  Árbol de procesos  Relación de jerarquías
  • 6.
    6 Proceso El sistema operativomantiene un conjunto de estructuras de información que permiten identificar y gestionar los procesos
  • 7.
    7 Proceso monothread omultithread  Un SO de multiprocesamiento se puede ejecutar varios procesos al mismo tiempo  Cada proceso se caracteriza por ser autónomo y una identidad indenpendiente y tienen su propio espacio de memoria  SO tiene un scheduler o planificador, el que decide cual proceso puede utilizar la CPU en un momento dado  En sistemas uni-procesador solo un proceso puede a la vez  Una característica de los procesos es que no comparten nada, son procesos separados shared nothing  Debe haber servicios en el SO que permitan compartir memoria  Aplicaciones múltiples hilos tiene varios puntos de ejecución o varios caminos o rutas en las cuales se pueden ejecutar las aplicaciones  Cada puntos de ejecución es llamado hilo  Los hilos comparten memoria
  • 8.
    8 Proceso monothread omultithread  Existen aplicaciones de un sólo hilo o hilo de ejecución  Si una aplicación tiene muchas tareas por ejecutar, solo una tarea se puede ejecutar a la vez  La tareas requieren mucho procesamiento puede parecer que la aplicación se ha congelado o no responde  Aplicaciones Multitheaded cada tarea esta ejecutada por un hilo  Permite que las aplicaciones sean más modulares donde cada tarea está en una tarea, y cada modulo está ejecudo por un hilo  Ejemplos:  Editor de documentos  Manejador de ventanas
  • 9.
    9 Proceso monothread omultithread  Un proceso ligero, hilo o thread es un programa en ejecución (flujo de ejecución) que comparte la imagen de memoria (y otras informaciones) con otros procesos ligeros  Dependiendo del número de procesos que puedan ejecutar simultáneamente, un SO es monotarea o multitarea  Un proceso ligero puede contener un solo flujo de ejecución (monothread) o más (multithread)  Por ejemplo, en el lenguaje C el hilo de ejecución primario se corresponde con la función principal main
  • 10.
    10 Hilo Información propia/compartida  Porthread (información propia)  Contador de programa, Registros  Pila  Estado (ejecutando, listo o bloqueado)  Por proceso (información compartida)  Espacio de memoria  Variables globales  Ficheros abiertos  Procesos hijos  Temporizadores  Señales y semáforos  Contabilidad
  • 11.
    11 Hilo Estructura de unproceso con threads
  • 12.
    12 Hilo Estructura de unproceso con threads  Cada hilo tiene su propio contexto, ej. registros, y las llamadas a pila  Quien selecciona el siguiente hilo a ejecutar  SO scheduleder  Procesos de usuario a ejecutar  Los programadores no pueden hacer ninguna presunción respecto a cómo los hilos son planificados, es aleatorio  Los SO, plataformas tienen sus propias políticas de planificación
  • 13.
    13 Hilo  Como losprocesos convencionales, un proceso ligero puede estar en varias situaciones o estados: ejecutando, listo o bloqueado  El estado del proceso será la combinación de los estados de sus procesos ligeros Estados del proceso ligero
  • 14.
    14 Hilo Threads y paralelismo Los procesos ligeros permiten paralelizar una aplicación  Un programa puede dividirse en procedimientos que pueden ejecutar de manera independiente mediante procesos ligeros  Los procesos ligeros pueden lanzar su ejecución de manera simultánea  Diseño modular de la aplicación  La base del paralelismo:  Mantener algún proceso ligero siempre en estado de ejecución: “mientras que un proceso está bloqueado otro podría estar ejecutando”
  • 15.
  • 16.
    16 Hilo Threads take advantageof multi-core systems
  • 17.
    17 Posix Posix Threds  Posix– Portable Operating System Interface  Define rutinas  Creación  Barrera sobre los hilos, puntos de sincronización  Otros  Matar  Inpeccionar características de los hilos
  • 18.
    18 Posix  Pthreads esla implementacipon de Posix thereads  Linux, Mac y Windows  Todos los programas que usen pthreads requiren incluir el archivo de cabecera pthread.h  Para compiar un programa en phtread  gcc pthread demo.c -o demo
  • 19.
    19 Posix Crear un thread: intpthread_create(pthread_t* thread, const pthread_attr_t* attr, void * (*funcion)(void *), void * arg); donde: thread Identificador del nuevo thread (se captura cuando se crea) attr Atributos a aplicar al nuevo thread o NULL funcion Función a ejecutar por el thread que es creado arg Puntero a el/los argumentos del thread devuelve: int 0 si éxito o -1 si error Obtener el identificador de un thread: pthread_t pthread_self(void);
  • 20.
    20 Posix Atributos de unproceso ligero:  Un hilo se crea con una serie de atributos por defecto  Ejemplo: Por defecto, un hilo es joinable o No Independiente  Es posible modificar los atributos por defecto del hilo:  Inicia un objeto atributo que se puede utilizar para crear nuevos procesos ligeros  int pthread_attr_init(pthread_attr_t *attr);  Destruye un objeto de tipo atributo  int pthread_attr_destroy(pthread_attr_t *attr);  Cambiar el estado de terminación (Joinable / Detached) int pthread_attr_setdetachstate( pthread_attr_t *a, int detachstate); Si detachstate es  PTHREAD_CREATE_DETACHED el proceso se crea independiente  PTHREAD_CREATE_JOINABLE el proceso se crea no independiente  Otras atributos: tamaño de pila, planificación, prioridad, etc.
  • 21.
    21 Posix Terminación de procesosligeros  Finaliza la ejecución del proceso ligero: int pthread_exit(void *value);  Para procesos creados como NO independientes es además necesario: int pthread_join(pthread_t thid, void **value);  pthread_t: identificador del hilo que se espere que termine  **value: se va almacenar el resultado de algunos valores que devuelva el hilo al terminar  Espera la terminación del proceso con identificador thid  Devuelve en el segundo argumento el valor pasado en pthread_exit.  Sólo se puede esperar la terminación de procesos ligeros no  independientes (PTHREAD_CREATE_JOINABLE)
  • 22.
    22 Ejemplos Práctica 1: Threads #include<pthread.h> #include <stdio.h> #define MAX 100 void *inc_x(void *x_void_ptr); int main(){ int x = 0; int y = 0; printf("x: %d, y: %dn", x, y); pthread_t inc_x_thread; if (pthread_create(&inc_x_thread, NULL, inc_x, &x)){ fprintf(stderr, "Error creating threadn"); return 2; } while (++y <MAX); printf("y increment finishedn"); printf("X: %d, y: %dn", x, y); return 0; } void *inc_x(void *x_void_ptr){ printf("I am in methodn"); int *x_ptr = (int *)x_void_ptr; while (++(*x_ptr) < MAX); printf("x increment finishedn"); return NULL; } hilo1_posix.cpp
  • 23.
  • 24.
    24 Ejemplos Práctica 1: Threads ¿Porquéx = 0? Porque en el primer ejemplo el programa no espera el hilo que termine su ejecución ¿Cómo hacemos que programa espere al hilo?
  • 25.
    25 Ejemplos Práctica 2: Threadshilo2_posix.cpp Agregar la función pthread_join para que el programa espere hasta que hilo termine su ejecución if(pthread_join(inc_x_thread, NULL)){ fprintf(stderr, "Error joining threadn"); return 2; }
  • 26.
    26 Ejemplos Práctica 2: Threadshilo2_posix.cpp #include <pthread.h> #include <stdio.h> #define MAX 100 void *inc_x(void *x_void_ptr); int main(){ int x = 0; int y = 0; printf("x: %d, y: %dn", x, y); pthread_t inc_x_thread; if (pthread_create(&inc_x_thread, NULL, inc_x, &x)){ fprintf(stderr, "Error creating threadn"); return 2; } while (++y <MAX); printf("y increment finishedn"); // esperamos al a todos los hilos if(pthread_join(inc_x_thread,NULL)){ fprintf(stderr, "Error joining threadn"); return 2; } printf("X: %d, y: %dn", x, y); return 0; } void *inc_x(void *x_void_ptr){ printf("I am in methodn"); int *x_ptr = (int *)x_void_ptr; while (++(*x_ptr) < MAX); printf("x increment finishedn"); return NULL; }
  • 27.
    27 Ejemplos Práctica 2: Threadshilo2_posix.cpp El tiempo de ejecución incrementa porque el programa ahora espera al hilo hasta que termine
  • 28.
    28 Hilos y concurrencia Setiene un vector de 15 elementos, se quiere buscar cuantas veces se repite 3 La complejidad del problema es O(n), porque se a ir comparando elemento por elemento y si se encontra un número 3 se va incrementando un contador for (i = 0; i > len(vector); i++) if (vector [ i ] == 3) count++
  • 29.
    29 Hilos y concurrencia Threadsand concurrency programa.cpp – hilo secuencial #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #define VECTOR_SIZE 100000000 // variables globales int *array; int count = 0; int double_count = 0; void initialize_vector(){ int i = 0; array = (int*) malloc(sizeof(int) * VECTOR_SIZE); if(array == NULL){ printf("Memoria no disponiblen"); exit(-1); } for(;i < VECTOR_SIZE; i++){ array[i] = rand() % 20; if (array[i] == 3) double_count++; } } void count_3s(){ int i = 0; for(;i < VECTOR_SIZE; i++){ if (array[i] == 3) count++; } }
  • 30.
    30 Hilos y concurrencia Threadsand concurrency programa.cpp – hilo secuencial int main(int argc, char* argv[]){ int i = 0; int err; clock_t t1, t2; printf("Running 3s-00"); srand(time(NULL)); printf("*** 3s-00 ***n"); printf("Initializing vector.... "); fflush(stdout); initialize_vector(); printf("Vector initialized! n"); fflush(stdout); t1 = clock(); count_3s(); t2 = clock(); printf("Count by thread %d!n",count); printf("Double check %d!n",double_count); printf("[[3s-00] tiempo transcurrido %fn",(((float)t2 - (float)t1) /1000000.0F) * 1000); printf("Finishing 3s-00"); return 0; }
  • 31.
    31 Hilos y concurrencia Threadsand concurrency hilo3_posix.cpp – hilo secuencial
  • 32.
  • 33.
    33 Hilos y concurrencia Threadsand concurrency hilo1_posix.cpp – hilo concurrente #define MAX_THREADS 8 int *array; int length = VECTOR_SIZE; int count = 0; int double_count = 0; // main …………. while(i < max_threads){ err = pthread_create(&tid[i], NULL, &count3s_thread, (void*)i); if (err != 0) printf("[3s-01] Can't create a thread [%ld]n",i); else printf("[3s-01] Thread created [%ld]n", i); i++; }
  • 34.
    34 Hilos y concurrencia Threadsand concurrency hilo1_posix.cpp – hilo concurrente #define MAX_THREADS 8 int *array; int length = VECTOR_SIZE; int count = 0; int double_count = 0; void *count3s_thread(void *arg){ int i; int length_per_thread = length / max_threads; long id = (long)arg; int start = id * length_per_thread; printf("nThread [%ld] starts [%d] length [%d]n", id, start, length_per_thread); for(i = start; i < start + length_per_thread; i++){ if (array[i] == 3){ count++; } } }
  • 35.
    35 Hilos y concurrencia Threadsand concurrency hilo1_posix.cpp – hilo concurrente Los count y double_count no son iguales Desface en lo que cuentan los hilos y la cuenta total
  • 36.
    36 Hilos y concurrencia Threadsand concurrency hilo1_posix.cpp – hilo concurrente
  • 37.
    37 Hilos y concurrencia hilo2_posix.cpp– hilo concurrente for(; i < max_threads; i++){ void *status; int rc; rc = pthread_join(tid[i],&status); if(rc){ printf("ERROR; return code from pthread() is %d n", rc); exit(-1); }else{ printf("Thread [%ld] exited with status [%ld] n", i, (long)status); } } La aplicación principal debería esperar a los hilos que se crearon
  • 38.
    38 Hilos y concurrencia hilo2_posix.cpp– hilo concurrente Tanto el count y el doube check no tienen el mismo valor Problemas de Concurrencia
  • 39.
    39 Hilos y concurrencia Problemasde Concurrencia El count es la variable común Tanto el hilo A y el hilo B acceden a una variables común ¿Cómo podemos resolver ese error?
  • 40.
    40 Hilos y concurrencia Problemasde Concurrencia Usar candados Hilo A lee count y le pone un candado para que ningún hilo pueda escribir en esa variable por otro hilo Se vuelve un algoritmo secuencial al acceso a datos
  • 41.
    41 Hilos y concurrencia pthread_mutex_tmutex; ……………………….. pthread_mutex_lock(&mutex); // se llama esta sección crítica for(i = start; i < start + length_per_thread; i++){ if (array[i] == 3){ count++; } } pthread_mutex_unlock(&mutex); …………………… //El candado que evita la concurrencia pthread_mutex_init(&mutex, NULL); pthread_mutex_destroy(&mutex);  Existe una nueva variable t_mutex que es un candado a traves pthread_mutex  En count3s_thread, cuando un hilo comienza a contar pone un candado sobre esa región de memoria donde se va a modificar cont, esta parte del código se le llama sección crítica  Inicialización el candado (mutex), la variable mutex a sido inicializada de forma global, todos los hilos la podrán ver
  • 42.
  • 43.
    43 Hilos y concurrencia Elproblema de la sección crítica  Sistema compuesto por n procesos  Cada uno tiene un fragmento de código: sección crítica  Los procesos deben acceder a la SC con exclusividad  Estructura general de cualquier mecanismo utilizado para resolver el problema de la sección crítica:  Requisitos que debe ofrecer cualquier solución para resolver el problema  de la sección crítica:  Exclusión mutua  Progreso  Espera limitada Entrada en la sección crítica Código de la sección crítica Salida de la sección crítica
  • 44.
    44 Hilos y concurrencia //pthread_mutex_lock(&mutex); for(i= start; i < start + length_per_thread; i++){ if (array[i] == 3){ pthread_mutex_lock(&mutex); count++; pthread_mutex_unlock(&mutex); } } //pthread_mutex_unlock(&mutex); ¿Qué sucede si se usa el bloqueo alrededor de declaraciones de código donde se modifica la variable compartida?
  • 45.
  • 46.
  • 47.
    47 Hilos y concurrencia //Definición de contadores privados para cada hilo int private_count[MAX_THREADS]; ************************************** for(i = start; i < start + length_per_thread; i++){ if (array[i] == 3){ private_count[id]++; // cambia } } // cambia... sección crítica pthread_mutex_lock(&mutex); count = count + private_count[id]; pthread_mutex_unlock(&mutex); Se crea un arreglo de variables privadas count Cada hilo recorre el segmento que le corresponde y podra contar con su contador y bloquea el count fuera del for
  • 48.
  • 49.
    49 Cŕeditos • Transparencias basadaspor: • Coulouris Dollimore, Distributed Systems: Concepts and Design https://ce.guilan.ac.ir/images/other/soft/distribdystems.pdf • García-Carballeira F., Tema 3 Comunicación y sincronización entre procesos http://ocw.uc3m.es/ingenieria-informatica/sistemas- distribuidos-2013/Tema3_ComunicacionYsincronizacion.pdf/view • Sanabria, John, Sistemas Distribuidos – Hilos – Prácticas, https://www.youtube.com/playlist?list=PLNqsgMwXL3mFmd8X8Fgv Z_6ljjzucIDbN
  • 50.
    Networking académico: Correo electrónico:rguaman@unl.edu.ec Twitter: @rene5254 SlideShare: https://es.slideshare.net/rene5254 50 Gracias