Códigos del curso

Práctica 3 — Candados clásicos y JMM

9 archivos Java · haz clic en cada uno para desplegarlo

Puedes copiar cada archivo desde aquí, o clonar el repositorio FC_CConcurrente completo:

git clone https://github.com/gilde-valeria/FC_CConcurrente.git

Archivos

Archivos

module-info.java8 líneas

Programas_P3/unam.fc.concurrent.practica3/src/module-info.java

/**
 * 
 */
/**
 * 
 */
module unam.fc.concurrent.practica3 {
}
Bakery.java51 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/Bakery.java

package unam.fc.concurrent.practica3;
import java.util.concurrent.atomic.*;
//Programa 5: Lamport's algorithm Unbounded

import unam.fc.concurrent.practica3.Nodo;

public class Bakery {
    private Nodo head;
    private Nodo tail;
    
    public Bakery() {
        this.head  = new Nodo(false, 0);
        this.tail  = new Nodo(false, 10000);
        while (!this.head.next.compareAndSet(null, this.tail));
    }
    public void lock(Nodo newnode) {
        Boolean added = false;
        Nodo last = null;
        
        while (!added) {
            if (this.tail.next.get() == null) {
                added = this.head.next.compareAndSet(this.tail, newnode);
                if (added) {
                    this.tail.next.compareAndSet(null, newnode);
                    last = head;
                }
            }else {
                last =  this.tail.next.get();
                added = last.next.compareAndSet(null, newnode);
                tail.next.compareAndSet(last, newnode);
            }
        }
        while (last.flag == true) {};
    }
    public void unlock(Nodo newnode) {
        newnode.flag = false;
    }
    public void print() {
        Nodo pred = this.head;
        Nodo curr = pred.next.get();
        System.out.println(pred.item);
        while (curr != null) {
          pred = curr;
          curr = curr.next.get();
          System.out.println(pred.item);
        }
    }
    

}
CounterNaive.java12 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/CounterNaive.java

package unam.fc.concurrent.practica3;

public class CounterNaive {
    private int count=0;
    public int increment() {
        return this.count++;
    }
    public int getValue() {
        return this.count;
    }
    
}
ExecuteBakery.java46 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/ExecuteBakery.java

package unam.fc.concurrent.practica3;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//Programa 4: Programa que ejecuta la clase Lamport's Bakery
// Este programa utiliza a su vez la clase Nodo

public class ExecuteBakery {
    
    public static void take(Bakery lock, CounterNaive counter) {
        Thread currentThread = Thread.currentThread();
        long id = currentThread.getId();
        Nodo node = new Nodo(true, (int) (id));
        try {
            lock.lock(node);
            Thread.sleep(5);
            counter.increment();
            //System.out.println("in ");
        }catch(InterruptedException e) {
            System.out.println(e);
        }finally {
            lock.unlock(node);      
        }
    }
     
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        Bakery lock = new Bakery();
        CounterNaive counter= new CounterNaive(); 
        
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for(int i = 0; i < 400; i++) {
            executor.execute(() -> take(lock, counter)); //Runnable al estilo lambda, esta notacion se usa en interfaces
        }
        try {
            Thread.sleep(5000);
            lock.print();
            System.out.println(counter.getValue());
        }catch(InterruptedException e) {
            System.out.println(e);
        }
    }
    
}
LockPeterson.java42 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/LockPeterson.java

package unam.fc.concurrent.practica3;
//Programa 3: Programa que ejecuta la clase Peterson, todas las variables utilizan volatile
// Utiliza la clase CounterNaive
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LockPeterson{
    
    private static void task(Peterson lock, CounterNaive counter) {
        try {
            lock.lock();
            counter.increment();
//          System.out.println(counter.getValue());
        }finally {
            lock.unlock();      
        }
    }
    
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Peterson lock = new Peterson();
        CounterNaive counter = new CounterNaive();
        ExecutorService executor = Executors.newFixedThreadPool(2);//El candado solo funciona para dos hilos
        
        for(int i = 0; i < 1000; i++) {
            executor.execute(() -> task(lock,counter)); 
        }
        executor.shutdown();
        
        try{
            Thread.sleep(500);
            System.out.println(counter.getValue());
        }catch(InterruptedException e) {
            System.out.println(e);
        }
    
    }

}
Nodo.java15 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/Nodo.java

package unam.fc.concurrent.practica3;

import java.util.concurrent.atomic.AtomicReference;

public class Nodo {
    public volatile Boolean flag; // Bandera que es true si quiero pasar y false si ya pase
    public AtomicReference<Nodo> next;
    public int item;
    public Nodo(Boolean flag, int item) {
        this.flag = flag;
        this.item = item;
        this.next = new AtomicReference<Nodo>(null);
    }
}
Peterson.java28 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/Peterson.java

package unam.fc.concurrent.practica3;


public class Peterson {
    private volatile boolean[] flag = new boolean[2];
    private volatile int victim;
    public void Peterson() {
        flag[0] = false; flag[1] = false;
        victim = 3;
    }
    public void lock() {
        Thread currentThread = Thread.currentThread();
        long id = currentThread.getId();
        int i = (int) (id % 2);
        int j = 1-i;
        flag[i] = true;
        victim = i;
        while (flag[j] && victim == i) {
        };
    }
    public void unlock() {
        Thread currentThread = Thread.currentThread();
        long id = currentThread.getId();
        int i = (int) (id % 2);
        flag[i] = false;
    }
}
VolatileExample1.java42 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/VolatileExample1.java

package unam.fc.concurrent.practica3;
//Programa 1: Programa que ejemplifica el problema de Visibilidad en el JMM 
// Si la variable flag no es volatile, entonces el hilo que ejecuta read() puede nunca leer que el 
//  hilo que ejecuta write() modifico flag
// Implica que volatile hace flush! a las modificaciones de flag

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class VolatileExample1 {
    static Boolean flag = false;
    
    private static void read() {
        
        while(!flag) {}
        
        System.out.println("La bandera esta en: " + flag);
    }
    private static void write() {
        try {
            Thread.sleep(1000); 
            flag = true;
            System.out.println("La bandera fue cambiada a true: " + flag);
        }
        catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ExecutorService executor = Executors.newFixedThreadPool(2);
         
        executor.execute(() -> write()); 
        executor.execute(() -> read());
        executor.shutdown();
        
    }

}
VolatileExample2.java59 líneas

Programas_P3/unam.fc.concurrent.practica3/src/unam/fc/concurrent/practica3/VolatileExample2.java

package unam.fc.concurrent.practica3;
//Programa 2: Programa que ejemplifica el problema de  Reordenamiento en el JMM
// Si no se utiliza volatile, entonces las lineas 15 a 18 se reordenan y el resultado de a y b es distinto
// Implica que volatile forza al compilador a no reordenar las instrucciones

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class VolatileExample2 {
    static Boolean flag = false;
    volatile static int a = 0, b = 0;
    
    private static void read() {
        
        while(!flag) {
            a = 0; 
            b += 1;
            b = a; 
            a += 1;}
        
        System.out.println("La bandera esta en: " + flag + " a: " +a +" b: " + b);
    }
    private static void write() {
        try {
            Thread.sleep(1000); 
            
            a = b;
            b = a;
            
            flag = true;
            b += 1;
            a += 1;
            System.out.println("La bandera fue cambiada a true: " + flag);
        }
        catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
    
        
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ExecutorService executor = Executors.newFixedThreadPool(2);
         
        executor.execute(() -> write());
        executor.execute(() -> read());
        
        executor.shutdown();
        try {
            Thread.sleep(1500);
            System.out.println("main: " + flag + " a: " +a +" b: " + b);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

}