- David Alejandro Vasquez Carreño
- Michael Jefferson Ballesteros Coca
Vamos a compilar el código con maven.
mvn compile
Para ejecutar la aplicación.
mvn exec:java -Dexec.mainClass="edu.eci.arsw.highlandersim.ControlFrame"
Para ejecutar las pruebas
mvn test
-
Chequeo de consumo de CPU en ejecución.
Este consumo es debido a que el consumidor hace una espera activa para verificar que la cola tenga elementos de los que sacar productos. Como regla, los threads o procesos que esperen a que un recurso se libere no deben hacer uso de cómputo.
while (true) { if (queue.size() > 0) { int elem=queue.poll(); System.out.println("Consumer consumes "+elem); } }
-
El consumo de CPU se va a mejorar a través del uso de wait() y notify() sobre la cola, de modo de que el consumidor no consuma recursos mientras la cola está vacía.
synchronized(queue){ if (queue.size() > 0) { int elem=queue.poll(); System.out.println("Consumer consumes "+elem); }else{ try { queue.wait(); } catch (Exception e) { //TODO: handle exception } } }
El bloque de sincronización pide el lock sobre el objeto y hace que el hilo consumidor espere si no hay elementos sobre la cola.
Del lado del productor, cada vez que insertemos nuevos elementos el la cola, notificamos a los hilos que estén esperando por este recurso.
synchronized(queue){
queue.notify();
}
Vemos que el consumo de CPU de ha reducido.
- Consumidor lento y productor rápido
La implementación es muy parecida a la del punto 2, pero el que va a esperar es el productor. El productor espera a que haya espacio.
PRODUCTOR
if(stockLimit>queue.size()){
dataSeed = dataSeed + rand.nextInt(100);
System.out.println("Producer added " + dataSeed);
queue.add(dataSeed);
}else{
synchronized(queue){
try {
queue.wait();
} catch (Exception e) {
//TODO: handle exception
}
}
}
CONSUMIDOR
synchronized(queue){
if (queue.size() > 0) {
int elem=queue.poll();
System.out.println("Consumer consumes "+elem);
queue.notify();
}
}
Vemos que el consumo de CPU se ha mantenido bajo.
RESPUESTAS
- Para N jugadores, ¿Cuál debería ser la suma de las vidas de los jugadores según el invariante?
De manera general, siendo N los jugadores y health la vida.
Vida total: N x health
De manera especifica: N x 100
2.Verificación del invariante
__PAUSA 1__
![](img/IMMORTALS/invarianteMal1.PNG)
__PAUSA 2__
![](img/IMMORTALS/invarianteMal2.PNG)
__PAUSA 3__
![](img/IMMORTALS/invarianteMal3.PNG)
Vemos que el invariante no se cumple 😧
3.Invariante luego de implementar la pausa COMPLETA de threads.
__PAUSA 1__
![](img/IMMORTALS/invarianteRound2-1.PNG)
__PAUSA 2__
![](img/IMMORTALS/invarianteRound2-2.PNG)
__PAUSA 3__
![](img/IMMORTALS/invarianteRound2-3.PNG)
Vemos que el invariante no se cumple 😐 aún
4.Identificación y solución de regiones críticas
Una región crítica que debe ser protegida con exclusión mutua es la pelea entre inmortales en el método fight.
if (i2.getHealth() > 0) {
i2.changeHealth(i2.getHealth() - defaultDamageValue);
this.health += defaultDamageValue;
updateCallback.processReport("Fight: " + this + " vs " + i2+"\n");
} else {
updateCallback.processReport(this + " says:" + i2 + " is already dead!\n");
}
Vamos a hacer la solución a través de un bloque sincronizado anidado.
5.Deadlock de inmortales
Vemos gracias a jstack, que ha habido un bloque mutuo entre threads.
jstack -l 16008
Dos threads están esperando por un monitor que ya poseen, por lo que se quedan esperando por siempre.
"im0":
at edu.eci.arsw.highlandersim.Immortal.fight(Immortal.java:80)
- waiting to lock <0x00000000c4fa06f8> (a edu.eci.arsw.highlandersim.Immortal)
- locked <0x00000000c4f9d180> (a edu.eci.arsw.highlandersim.Immortal)
at edu.eci.arsw.highlandersim.Immortal.run(Immortal.java:68)
"im1":
at edu.eci.arsw.highlandersim.Immortal.fight(Immortal.java:80)
- waiting to lock <0x00000000c4f9d180> (a edu.eci.arsw.highlandersim.Immortal)
- locked <0x00000000c4fa06f8> (a edu.eci.arsw.highlandersim.Immortal)
at edu.eci.arsw.highlandersim.Immortal.run(Immortal.java:68)
6.Implementación con lista concurrente
Al eliminar elementos de manera concurrente, sube la posibilidad de acceder a indices vacíos del arreglo.
Entre más inmortales haya, más accesos aleatorios se harán en la lista, pero al mismo tiempo se eliminan elementos. Se debe controlar los accesos a la lista con excepciones si no se quiere hacer sincronización.
- Maven - Manejo de dependencias
- Alejandro Vasquez - Extender - alejovasquero
- Michael Ballesteros - Extender - Wasawsky