Examenes Programación Concurrente
✓ Acierto: +1
✗ Fallo: −1
— No contesta: 0
Puntuación total
—
0
Correctas
0
Incorrectas
0
Sin responder
1
Dada la implementación del Buffer Limitado, selecciona la opción correcta o rellena cada hueco ▣ en el código.
Código con huecos · +1/−1
Los menús desplegables son los huecos del código
public class BufferLimitado {
protected Object[] buffer;
private int elementos_utilizados;
private static final int LLENO=0, PARCIAL=1, VACIO=2;
private final int CAPACIDAD;
private int ptrput, ptrtake;
private int estado;
public BufferLimitado(int tamaño) {
CAPACIDAD = tamaño;
ptrput = 0;
ptrtake = ; // opciones: 0, 1, tamaño+1, tamaño
elementos_utilizados = 0;
estado = ; // opciones: PARCIAL, 5, VACIO, ESPERANDO, LLENO
buffer = new Object[tamaño];
}
updateStateNotify() { // opciones: protected synchronized void, public void, public synchronized void, protected void
int antiguoEstado = estado;
if (elementos_utilizados == 0)
estado = VACIO;
else if (elementos_utilizados == CAPACIDAD)
estado = LLENO;
else
estado = PARCIAL;
if (estado != antiguoEstado && antiguoEstado != ) // opciones: ESPERANDO, PARCIAL, LLENO, VACIO
;
}
void put(Object o) throws InterruptedException { // opciones: protected synchronized, public, public synchronized, protected
beforePut();
buffer[ptrput] = o;
ptrput = (ptrput + 1) % CAPACIDAD;
elementos_utilizados += 1;
;
return;
}
beforePut() throws InterruptedException { // opciones: protected synchronized void, public void, public synchronized void, protected void
while (estado == ) { // opciones: PARCIAL, VACIO, ESPERANDO, LLENO
;
}
}
Object take() throws InterruptedException { // opciones: protected synchronized, public, public synchronized, protected
beforeTake();
Object o = buffer[ptrtake];
ptrtake = (ptrtake + 1) % CAPACIDAD;
elementos_utilizados -= 1;
;
return o;
}
beforeTake() throws InterruptedException { // opciones: protected synchronized void, public void, public synchronized void, protected void
while (estado == ) { // opciones: VACIO, LLENO, PARCIAL
;
}
}
}
2
Describe un caso de ejecución de un programa concurrente en el que se lance la excepción
Respuesta abierta
IllegalMonitorStateException.Respuesta del profesor
Las entidades que poseen tanto cerrojos como conjuntos de espera se denominan monitores. La clase java.lang.Object puede servir de monitor: tiene un cerrojo (synchronized) y un conjunto de espera que manipula mediante wait, notify, notifyAll, Thread.interrupt.Los métodos
wait, notify, notifyAll sólo se pueden invocar cuando el hilo haya adquirido el cerrojo del objeto. Si se invocan sin tenerlo, se lanza IllegalMonitorStateException.Ejemplo: llamar a
obj.notify() fuera de un bloque synchronized(obj).
3
Precondiciones del patrón bloqueo lectura/escritura. Rellena la tabla con las precondiciones de
Respuesta abierta
permitirLeer() y permitirEscribir() usando las variables lectoresActivos, escritoresActivos, lectoresEsperando, escritoresEsperando.| lectoresActivos | escritoresActivos | lectoresEsperando | escritoresEsperando | |
|---|---|---|---|---|
permitirLeer() | ||||
permitirEscribir() |
Respuesta del profesor
| lectoresActivos | escritoresActivos | lectoresEsperando | escritoresEsperando | |
|---|---|---|---|---|
permitirLeer() | cualquier valor | == 0 | cualquier valor | == 0 |
permitirEscribir() | == 0 | == 0 | cualquier valor | cualquier valor |
4
Clase Ball.java del juego de billar concurrente. Rellena los huecos relacionados con la exclusión mutua e invariantes.
Código con huecos · +1/−1
Los menús desplegables son los huecos del código
Diagrama de actividad UML — 4 hilos en paralelo (move → reflect → repaint)
Interfaz del juego — bolas moviendose concurrentemente
import java.awt.Image;
import javax.swing.ImageIcon;
public class Ball {
private String Ball = "Ball.png";
private double x, y, dx, dy;
private double v, fi;
private Image image;
public Ball() {
ImageIcon ii = new ImageIcon(this.getClass().getResource(Ball));
image = ii.getImage();
x = Billiards.Width/4-16;
y = Billiards.Height/2-16;
v = 5; fi = 0.5;
}
public void move() { // exclusión mutua
v = v * Math.exp(-v/1000);
dx = v * Math.cos(fi);
dy = v * Math.sin(fi);
if (Math.abs(dx) < 1 && Math.abs(dy) < 1) { dx = 0; dy = 0; }
x += dx; y += dy;
; // invocar invariante
}
public synchronized void reflect() {
if (Math.abs(x + 32 - Board.RIGHTBOARD) < 2) fi = Math.PI - fi;
if (Math.abs(y + 32 - Board.BOTTOMBOARD) < 2) fi = -fi;
if (Math.abs(x - Board.LEFTBOARD) < 2) fi = Math.PI - fi;
if (Math.abs(y - Board.TOPBOARD) < 2) fi = -fi;
; // invocar invariante
}
public getX() { return (int) x; }
public getY() { return (int) y; }
public double getFi() { return fi; }
public double getdr() { return Math.sqrt(dx*dx + dy*dy); }
public setX(double x) { this.x = x; } // exclusión mutua
public synchronized void setY(double y) { this.y = y; }
public Image getImage() { return image; }
protected void check() {
Board.LEFTBOARD <= getX() && getX() <=
&& Board.TOPBOARD <= getY() && getY() <=
: "INV: La bola está fuera del tablero";
}
}
5
Asocia cada tipo de confinamiento con su descripción.
Asociación · +1/−1
Implica una práctica de programación ordinaria relacionada con variables locales.
Técnicas de encapsulamiento OO para asegurar la unicidad de acceso en métodos que incorporan objetos.
Técnicas para restringir el acceso dentro de hilos.
Amplía las técnicas a conjuntos de colaboración de objetos que operan a través de múltiples hilos.
6
Relaciona cada gráfica que modela una ejecución concurrente con múltiples hilos con su correspondiente concepto de programación concurrente.
Asociación · +1/−1
7
¿Cuál de las siguientes modificaciones serían necesarias para diseñar la clase
Selección múltiple · +1/−1
RGB con un patrón inmutable?public class RGB {
private int red, green, blue;
private String name;
public RGB(int red, int green, int blue, String name) {
super();
this.red = red; this.green = green;
this.blue = blue; this.name = name;
}
public void setRGB(int red, int green, int blue, String name) {
this.red = red; this.green = green;
this.name = name;
}
}
8
Sincronización con
Completar huecos · +1/−1
synchronized — selecciona la opción correcta en cada hueco ▼ del texto.🔒 Protocolo de cerrojo
Protocolo de adquisición y liberación definido con la palabra reservada
Un cerrojo: Se
a la entrada del método o bloque synchronized
Se
a la salida incluso si se termina con el lanzamiento de una excepción
🧵 Avance del hilo
Los cerrojos funcionan en el contexto de hilos y no en la invocación de métodos. Un hilo avanza por un método synchronized si el cerrojo está
o el hilo posee ya el cerrojo
En otro caso el hilo se
🔁 Reentrada (bloqueo intrínseco)
El bloqueo intrínseco se diferencia de la política usada por defecto por hilos POSIX (bloqueo reentrante). Un método synchronized puede hacer una llamada a otro método synchronized
sin que se paralice
En otro caso el hilo se
⚡ Métodos no sincronizados
Un método o bloque synchronized se corresponde con un protocolo de adquisición y liberación de cerrojos con respecto a otros métodos synchronized y bloques del mismo objeto destino. Los métodos no synchronized
ejecutarse en cualquier momento incluso si un método synchronized se está ejecutando
📋 Garantías del sistema
Cuando un hilo libera un cerrojo, otro hilo puede adquirirlo.
hay garantía de cuál de los hilos bloqueados adquirirá el cerrojo
hay mecanismo para descubrir si un cerrojo fue adquirido por algún hilo
9
Dado el monitoreo con JVisualVM de una aplicación concurrente, contesta sobre el estado de los hilos. Selecciona una o más.
Selección múltiple · +1/−1
JVisualVM — estados de Thread-0 a Thread-7 a lo largo del tiempo (Running, Sleeping, Wait, Monitor)
10
¿Cuáles de estos métodos de Java sirven para implementar el monitor de Hoare para resolver dependencias de estados? Selecciona una o más.
Selección múltiple · +1/−1
11
Asocia los números del diagrama de transición de estados con los estados/eventos de los hilos en Java (
Asociación · +1/−1
java.lang.Thread).Identifica el número del diagrama con el estado/evento correspondiente
1
2
3
4
5
6
12
La imagen muestra las distintas estructuras de ejecución concurrente. Indica tres contextos de aplicación donde sería interesante utilizar cada una de las siguientes estructuras: (1) Directa desde JRE · (2)
Respuesta abierta
Executors.newFixedThreadPool(MAXTHREADS) · (3) Executors.newCachedThreadPool().Jerarquía de estructuras de ejecución: llamada → tarea → hilo → proceso → sistema distribuido
Respuesta del profesor
(1) Directa desde JRE — Número de hilos fijo durante toda la ejecución. Aplicaciones de domótica con lectura/escritura de dispositivos hardware (termómetro, acelerómetro…): se modela un hilo independiente por cada dispositivo.(2)
Executors.newFixedThreadPool(MAXTHREADS) — Gestión de servicios de conexiones de red con número de hilos desconocido a priori y costosos. Permite ajustar el pool a las características hardware concretas donde se ejecuta la aplicación.(3)
Executors.newCachedThreadPool() — Aplicación de gestión de eventos: muchas tareas pequeñas que pueden coincidir en el tiempo sin comportamientos preestablecidos. Se crean hilos a demanda y se comparten (bajo coste por tarea vs. por hilo).
13
Respecto a la dependencia de estados lógicos en programación concurrente, ¿cuáles son ciertas?
Selección múltiple · +1/−1
14
Respecto al patrón productor-consumidor, ¿cuáles son verdaderas?
Selección múltiple · +1/−1
15
Define un esquema de código Java que establezca una estrategia segura de recorridos de colecciones en entornos concurrentes con bloqueos en el cliente.
Respuesta abierta
Respuesta del profesor
Estrategia: bloqueo en el cliente sobre colecciones sincronizadas.
Collection c = Collections.synchronizedCollection(myCollection);
synchronized (c) {
Iterator i = c.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
Se sincroniza manualmente el bloque que contiene el iterador, usando el mismo objeto colección como monitor.
16
¿Cuáles de las siguientes sentencias sobre los hilos de Java son ciertas?
Selección múltiple · +1/−1
17
Respecto a la inmutabilidad, ¿cuáles son verdaderas?
Selección múltiple · +1/−1
18
La siguiente aplicación Java lanza dos hilos. Cada uno escribirá n veces un carácter por pantalla. El primer hilo escribe 10 veces el carácter
Rellena los huecos para que se cumplan las especificaciones.
Completar código · +1/−1
'x', el segundo 100 veces el carácter 'o'. Cada vez que se imprime un carácter, el hilo duerme un intervalo de tiempo pasado como parámetro en su construcción. También se puede configurar n y el carácter.Rellena los huecos para que se cumplan las especificaciones.
public class CasoEstudioHilosBasico { public static void main(String[] args) { Thread t1 = new (new HiloImpresor('', 10, 10)); t1.(); Thread t2 = new (new HiloImpresor('', 10, 100)); t2.(); } } public class HiloImpresor implements { private final char caracter; private final int sleepTime; private final int repeticiones; public HiloImpresor(char caracter, int sleepTime, int repeticiones) { this.caracter = caracter; this.sleepTime = sleepTime; this.repeticiones = repeticiones; } public () { for (int i = 0; i < ; i++) { try { System.out.print(); Thread.sleep(); } catch ( e) { e.printStackTrace(); return; } } } }
19
En la primera práctica de la asignatura de programación concurrente se presentó, en un repositorio de Github, una biblioteca Java que permitía analizar páginas html.
Respuesta abierta
- ¿Para qué utiliza la biblioteca la programación concurrente?
- ¿Qué ventajas e inconvenientes proporciona el uso de la programación concurrente respecto a una solución secuencial?
- ¿Existen problemas de exclusión mutua y de dependencias de estados? Justifica la respuesta identificando los hilos, el programa lanzador y objeto pasivos.
Respuesta del profesor
Biblioteca con la programación concurrente (ver https://github.com/yasserg/crawler4j). Consulta el foro con la primera práctica de la asignatura.
¿Para qué utiliza la programación concurrente?
Inspecciona varias páginas al mismo tiempo.
¿Qué ventajas e inconvenientes proporciona el uso de programación concurrente respecto a una solución secuencial?
Disminuye el tiempo de ejecución al reducir las esperas de conexión a los servidores html.
¿Puedes proporcionar un ejemplo de código?
Ejemplo de varios crawlers funcionando de forma concurrente.
Diagrama de actividad: modela una configuración concurrente de una aplicación Java con dos controladores cada uno con una configuración concurrente distinta (1 y 2 hilos respectivamente) y que rastrean dos dominios/sites diferentes cada uno. Importante observar las estructuras concurrentes en el flujo de ejecución de sólo un inicio y sólo un fin.
¿Para qué utiliza la programación concurrente?
Inspecciona varias páginas al mismo tiempo.
¿Qué ventajas e inconvenientes proporciona el uso de programación concurrente respecto a una solución secuencial?
Disminuye el tiempo de ejecución al reducir las esperas de conexión a los servidores html.
¿Puedes proporcionar un ejemplo de código?
Ejemplo de varios crawlers funcionando de forma concurrente.
Diagrama de actividad: modela una configuración concurrente de una aplicación Java con dos controladores cada uno con una configuración concurrente distinta (1 y 2 hilos respectivamente) y que rastrean dos dominios/sites diferentes cada uno. Importante observar las estructuras concurrentes en el flujo de ejecución de sólo un inicio y sólo un fin.
Diagrama de actividad — MultipleCrawlerController con crawlers concurrentes
20
Asocia cada imagen de monitorización de hilos en Java, de la misma aplicación, con su servicio de ejecución (
Asociación · +1/−1
java.util.concurrent.ExecutorService) correspondiente.Puntuación total
—
0
Correctas
0
Incorrectas
0
Sin responder
1
Completa los huecos del código
Código con huecos · +1/−1
BufferLimitado seleccionando la opción correcta en cada desplegable ▣. Los menús desplegables son los huecos del código
public class BufferLimitado {
protected Object[] buffer;
private int elementos_utilizados;
private static final int LLENO=0, PARCIAL=1, VACIO=2;
private final int CAPACIDAD;
private int ptrput, ptrtake;
private int estado;
public BufferLimitado(int tamaño) {
CAPACIDAD = tamaño;
ptrput = 0;
ptrtake = ; // 0, 1, tamaño+1, tamaño
elementos_utilizados = 0;
estado = ; // PARCIAL, 5, VACIO, ESPERANDO, LLENO
buffer = new Object[tamaño];
}
updateStateNotify() {
int antiguoEstado = estado;
if (elementos_utilizados == 0) estado = VACIO;
else if (elementos_utilizados == CAPACIDAD) estado = LLENO;
else estado = PARCIAL;
if (estado != antiguoEstado && antiguoEstado != )
;
}
void put(Object o) throws InterruptedException {
beforePut();
buffer[ptrput] = o;
ptrput = (ptrput + 1) % CAPACIDAD;
elementos_utilizados += 1;
updateStateNotify();
return;
}
beforePut() throws InterruptedException {
while (estado == ) {
;
}
}
Object take() throws InterruptedException {
beforeTake();
Object o = buffer[ptrtake];
ptrtake = (ptrtake + 1) % CAPACIDAD;
elementos_utilizados -= 1;
updateStateNotify();
return o;
}
beforeTake() throws InterruptedException {
while (estado == ) {
;
}
}
}
2
Implementación de la clase
Código con huecos · +1/−1
Dato con patrón productor-consumidor usando ReentrantLock. Rellena los huecos ▣. Los menús desplegables son los huecos del código
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Dato {
private int dato = -1;
private boolean sePuedeEscribir = true;
private ReentrantLock lock = new ReentrantLock();
private Condition condicion = lock.newCondition();
void setDato(int val) {
lock.;
try {
while () {
try {
;
} catch (InterruptedException e) {}
}
dato = val;
sePuedeEscribir = ;
;
} finally {
lock.;
}
}
int getDato() {
lock.;
try {
while () {
try {
;
} catch (InterruptedException e) {}
}
sePuedeEscribir = ;
;
return dato;
} finally {
lock.unlock();
}
}
}
3
Dada la síntesis funcional de cuatro aplicaciones concurrentes, selecciona el problema concurrente asociado a cada una.
Selección por subapartado · +1/−1
A. Varios hilos calculan estadísticas y acumulan resultados en variables locales, luego las combinan al final.
B. Varios hilos incrementan una variable compartida que cuenta el número total de visitas a una web.
C. Un hilo genera tareas en una cola y otro hilo las procesa en orden.
D. Varios hilos leen simultáneamente datos de un fichero sin modificarlo.
Puntuación total
—
0
Correctas
0
Incorrectas
0
Sin responder
⚠️ Las preguntas que faltan es porque han aparecido en el examen de 2025. Dado que las capturas de este examen no muestran las respuestas del profesor, es posible que haya alguna respuesta incorrecta.
1
Respecto a las estrategias para garantizar la exclusión mutua, ¿Cuál de las siguientes sentencias son ciertas?
Selección múltiple · +1/−1
3
En el paquete
— Las características de diseño de los programas concurrentes.
— Su solución respecto al problema de exclusión mutua.
Respuesta abierta
java.util existen dos implementaciones de colecciones con una funcionalidad equivalente ArrayList y Vector. Justifica la existencia de estas dos clases con la misma funcionalidad, basándote en:— Las características de diseño de los programas concurrentes.
— Su solución respecto al problema de exclusión mutua.
Respuesta modelo
Vector es una clase thread-safe: todos sus métodos están sincronizados (synchronized), lo que garantiza la exclusión mutua cuando varios hilos acceden concurrentemente. Sin embargo, esta sincronización tiene un coste de rendimiento.ArrayList no es thread-safe: no sincroniza sus métodos, lo que la hace más eficiente en entornos de un solo hilo o cuando la sincronización se gestiona externamente.La existencia de ambas se justifica por las imposiciones de diseño concurrente: en los diseños concurrentes existe un compromiso entre seguridad (safety) y rendimiento (throughput). Los diseños basados en seguridad son más lentos.
Vector prioriza la seguridad; ArrayList prioriza el rendimiento. Según el contexto, el programador elige una u otra.
6
Bloqueo de lectura y escritura. Dada la siguiente captura de pantalla correspondiente a una simulación de bloqueos de lectura y escritura, selecciona cuál ha sido la secuencia de bloqueos realizada. RL = bloqueo de lectura; WL = bloqueo de escritura.
Selección única · +1/−1
Simulación ReadWriteLock — Waiting to acquire READ lock
//Construct the ReadWriteLock
final ReadWriteLock lock =
new ReentrantReadWriteLock();
new ReentrantReadWriteLock(true);
//Acquire the read lock
try {
lock.readLock().lock();
//or
lock.readLock().tryLock(1L, TimeUnit.SECONDS);
} catch (InterruptedException e){}
//Release the read lock
lock.readLock().unlock();
//Acquire the write lock
try {
lock.writeLock().lock();
}
8
La siguiente implementación de
Rellena los huecos para que el código compile correctamente.
Completar código · +1/−1
EagerSingletonCounter aplica el patrón Singleton en entornos concurrentes. La solución evita la inicialización retardada y sincroniza completamente el objeto.Rellena los huecos para que el código compile correctamente.
Los menús desplegables son los huecos del código
class EagerSingletonCounter {
private final long initial;
private long count;
final EagerSingletonCounter s = new ;
EagerSingletonCounter() {
initial = Math.abs(new java.util.Random().nextLong() / 2);
count = initial;
}
public EagerSingletonCounter instance() {
return ;
}
public long next() {
return count++;
}
public void reset() {
count = initial;
}
}
9
Respecto a los objetos completamente sincronizados. ¿Cuál de las siguientes afirmaciones es verdadera?
Selección múltiple · +1/−1
11
En el paquete
Describe textualmente qué ocurre cuando se producen las siguientes llamadas concurrentes:
Respuesta abierta
java.util.concurrent.locks se proporciona una implementación de bloqueo reentrante con la clase Lock. En la siguiente imagen se muestra una simulación: hay un hilo ejecutándose y otros seis están bloqueados. De los seis hilos bloqueados los tres primeros han sido bloqueados con lock() y los tres últimos con lockInterruptibly().Describe textualmente qué ocurre cuando se producen las siguientes llamadas concurrentes:
Simulación ReentrantLock — 1 hilo ejecutándose, 6 bloqueados
// Constructor
final Lock lock = new ReentrantLock();
lock.lock();
try {
lock.lockInterruptibly();
} catch (InterruptedException e) { ... }
lock.unlock();
boolean acquired = false;
try {
acquired = lock.tryLock(1L, TimeUnit.SECONDS);
if(acquired) {
doSomething();
}
} catch (InterruptedException e) { ...
} finally {
if (acquired) {
lock.unlock();
}
}
<lockedThread>.interrupt();
<blockedThread>.interrupt();
Describe qué ocurre en cada caso:
- Se invoca al método
lock.lock() - Se invoca al método
lock.unlock() - Se invoca al método
lock.tryLock() - Se invoca la
interrupción.interrupt()sobre el hilo con el cerrojo - Se invoca el
método.interrupt()sobre un hilo bloqueado
Respuesta modelo
lock.lock()— Se añade un nuevo hilo a la cola de espera. El hilo queda bloqueado porque el cerrojo ya está adquirido por otro hilo. No se puede interrumpir una vez bloqueado conlock().lock.unlock()— El hilo que posee el cerrojo lo libera. Uno de los hilos en espera (el primero de la cola) adquiere el cerrojo y continúa su ejecución. Si el hilo que posee el cerrojo llama aunlock()más veces de las que llamó alock(), se lanzaIllegalMonitorStateException.lock.tryLock()— Intenta adquirir el cerrojo sin bloquearse. Si el cerrojo está libre, lo adquiere y devuelvetrue. Si está ocupado, devuelvefalseinmediatamente (o espera el tiempo indicado si se usa la versión con timeout).interrupt()sobre el hilo con el cerrojo — No tiene efecto inmediato sobre la posesión del cerrojo. El hilo sigue ejecutándose normalmente pero se activa su flag de interrupción. Si el hilo ejecuta una operación bloqueante (comowait(),sleep()), entonces recibirá unaInterruptedException.interrupt()sobre un hilo bloqueado — Depende de cómo fue bloqueado:
• Si fue bloqueado conlock(): la interrupción no desbloquea al hilo. Solo se activa el flag de interrupción.
• Si fue bloqueado conlockInterruptibly(): el hilo se desbloquea, sale de la cola de espera y se lanzaInterruptedException.
15
Respecto al problema de dependencias de estados lógicos en programación concurrente, ¿cuál de las siguientes sentencias son ciertas?
Selección múltiple · +1/−1
17
Dada la definición de la clase
Completar tabla · +1/−1
Celda y suponiendo que existen dos hilos (T1 y T2) que están utilizando dos objetos de tipo Celda (a y b), termina de describir la situación de interbloqueo seleccionando la acción correcta en cada celda ▼ de la tabla.class Celda {
private long valor;
synchronized long getValor() { return valor; }
synchronized void setValor(long v) { valor = v; }
synchronized void intercambiarValor(Celda otro) {
long t = getValor();
long v = otro.getValor();
setValor(v);
otro.setValor(t);
}
}
| t | T1 Acciones del hilo T1 | T2 Acciones del hilo T2 |
|---|---|---|
| 1 | Adquiere el cerrojo sobre a al entrar a ejecutar a.intercambiarValor(b) |
— |
| 2 | ||
| 3 | ||
| 4 |
Selecciona la acción correcta en cada celda de la tabla
19
Seleccione las afirmaciones correctas relacionadas con las imposiciones de diseño concurrente en Java.
Selección múltiple · +1/−1