Cómputo Concurrente 2026

Repaso de Java e introducción a la programación multihilos

Práctica 1

Contexto

“La necesidad de sincronización surge siempre que existan operaciones que se ejecutan de forma concurrente sin importar si realmente se ejecutan en paralelo” (Michael L. Scott 30 January 2024).

Esta observación data de los años 60’s por Edsger Dijkstra, a pesar de que las arquitecturas multiprocesador surgen a inicios de los 2000’s, las arquitecturas multihilo surgen antes.

En una arquitectura multihilo un solo procesador tiene la capacidad de seguir múltiples programas de ejecución distintos sin la necesidad de la intervención del software, ya que esto requeriría múltiples ciclos del procesador. En cambio, permite cambiar de un programa de ejecución o hilo a otro a partir del almacenamiento de los estados de los hilos en el hardware, esto potencia el uso más eficiente de recursos del procesador, como se observa en la Figura 1.

Las primeras máquinas con arquitecturas de multihilos surgieron en los años 50’s, la DYSEAC y la SEAC (Mario Nemirovsky 17 January 2013).

Imagen obtenida de (Mario Nemirovsky 17 January 2013)

Una arquitectura multiprocesador está conformada por múltiples procesadores, permite ejecutar dos hilos o más en el mismo ciclo, es decir, de forma paralela debido a que los recursos de ejecución de cada hilo están distribuidos en los procesadores, y los procesadores a su vez tienen múltiples cores. En la Figura 2 se muestra un ejemplo de una arquitectura moderna, en donde cada procesador tiene múltiples cores, los cuales comparten determinadas instancias de memoria (Caché \(L1\), \(L2\), \(L3\), etc) y se comunican por un bus de memoria unificada. En la actualidad cada \(core\) tiene la capacidad de almacenar más de un hilo (Intel 2024). Cada arquitectura es distinta dependiendo el fabricante.

Imagen obtenida de (Michael L. Scott 30 January 2024)

Los hilos/procesos se utilizan de forma diferente según distintos autores, por ejemplo, según Linus Torvalds un hilo/proceso es simplemente un contexto de ejecución. Sin embargo, en el curso consideraremos las definiciones a continuación:

Un proceso es un programa en ejecución. Un hilo es un proceso que puede ejecutarse de forma paralela con otros hilos concurrentes y compartir recursos (por ejemplo: variables).

Un proceso también se puede considerar como un conjunto de hilos que comparten el espacio del proceso (memoria, disco, cpu, etc).

Multihilos en Java

Arquitectura de JVM.

Imagen obtenida de (Lipsky 2023)

En la Figura 4 se muestra la anatomía de la JVM, sin embargo, en este curso nuestras áreas de interés son: Thread Synchronization y Memory Management.

Un hilo en Java se implementa por un hilo nativo del sistema operativo, cada hilo tiene una región de memoria reservada la cual se denota como la stack de cada hilo. Cada stack contiene variables locales y configuraciones de métodos que son ejecutados por el hilo (El tamaño de las stacks es una variable en la JVM).

En relación con la asignación de memoria en Java, cada objeto nuevo creado con el operador new reside en la memoria llamada Java heap, la cual está especificada por la JVM (y no por los programadores). Sin embargo, esta heap debe ser rápida y thread-safe, es por eso que cada hilo tiene su propia región en esta heap.

Representación de la Memoria en Java

Hilos en Java.
Un hilo en Java es una instancia de la clase java.lang.Thread (https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html), se crean como cualquier otro objeto en Java. Podemos crear un hilo de dos formas distintas:

  1. Extendiendo la clase Thread y sobrescribiendo el método run()

  2. Implementando la interfaz Runnable para pasarla como argumento de un objeto de la clase Thread.

Un hilo de la clase Thread tiene los siguientes atributos:

\(\diamond\) ID

\(\diamond\) Nombre

\(\diamond\) Prioridad

\(\diamond\) Status: Consta de 5 estados.
Los 5 estados son los siguientes:

  1. New: El hilo se ha creado pero no ha empezado

  2. Runnable: El hilo está siendo ejecutado por la JVM

  3. Blocked: El hilo está bloqueado y está esperando por un monitor (\(sleep()\), \(await()\))

  4. Timed\(\_\)waiting: Un hilo está esperando a otro por un lapso de tiempo específico

  5. Terminated: Un hilo ha terminado su ejecución

Ejemplos

En el siguiente link: https://github.com/surindt/FC_CConcurrente/tree/main/Programas_P1

Ejercicios

Instrucciones:

Tiempo de elaboración:\(\approx\) 1.5hr

Total de puntos: 100

  1. Lee lo siguiente https://www.evanjones.ca/software/threading-linus-msg.html y comparte en máximo 4 líneas de computadora a que se refiere Linus Torvalds con un contexto de ejecución y cómo se relaciona con la definición en la sección 1 de esta práctica.

  2. ¿Cuántos hilos tiene disponibles tu computadora?

    Ejecuta Runtime.getRuntime().availableProcessors(), si son más de uno en el equipo escriban el de cada uno.

  3. Revisa el programa Determinante concurrente y responde ¿Cuánto tiempo tarda en ejecutarse?

  4. El programa Determinante concurrente está implementado extendiendo la clase Thread. Implementa el programa utilizando la interfaz Runnable.

  5. Implementa el programa Determinante concurrente de forma secuencial.

  6. Implementa del programa Determinante concurrente para dos hilos (en vez de seis).

  7. Compara las 3 implementaciones: el programa Determinante concurrente para dos hilos, para seis hilos y el programa secuencial. Responde: ¿A qué se debe el orden en el que se ordenan los tiempos de ejecución de cada programa?

  8. Si utilizas la Ley de Amdahl entre el programa Determinante concurrente para dos hilos y el programa secuencial. ¿El resultado es mayor o menor a 1? ¿Por qué?

  9. Describe con tus propias palabras en máximo dos líneas para qué sirve el método join(). Si no utilizas el método join() en Determinante Concurrente, ¿sigue funcionando?

Intel. 2024. «What Is Hyper-Threading?» https://www.intel.com/content/www/us/en/gaming/resources/hyper-threading.html#:~:text=Intel®%20Hyper%2DThreading%20Technology%20is%20a%20hardware%20innovation%20that,can%20be%20done%20in%20parallel.].
Lipsky, Nikita. 2023. «JVM Anatomy 101». Youtube; https://youtu.be/BeMi8K0AFAc?si=X56D_vzpp-u7iNH9.
Mario Nemirovsky, Dean M. Tullsen. 17 January 2013. Multithreading Architecture. Springer Cham.
Michael L. Scott, Trevor Brown. 30 January 2024. Shared-Memory Synchronization. Springer Cham.