package ar.com.javacuriosities.concurrency.reentrant_lock; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* * ReentrantLock es la implementación de la interfaz Lock en este caso * nos brinda exclusion mutua entre varios threads * */ public class Main { public static void main(String[] args) { // Creamos el Lock de exclusion mutua Lock lock = new ReentrantLock(); // Creamos un Pool de 3 hilos ExecutorService executor = Executors.newFixedThreadPool(3); // Creamos un recurso compartido SharedResource sharedResource = new SharedResource(); // Creamos 3 tareas y le pasamos el recurso y el lock que sirve de monitor Runnable task1 = new Worker("Worker-1", lock, sharedResource); Runnable task2 = new Worker("Worker-2", lock, sharedResource); Runnable task3 = new Worker("Worker-3", lock, sharedResource); // Ejecutamos las tres tareas executor.execute(task1); executor.execute(task2); executor.execute(task3); // No aceptamos nuevas tareas executor.shutdown(); } /* * Este Worker va a ir usando el recurso compartido pero antes de usarlo * va a hacer un lock en el monitor para asegurar que nadie mas va a usarlo * al mismo tiempo */ private static final class Worker implements Runnable { private Lock lock; private String name; private SharedResource sharedResource; public Worker(String name, Lock lock, SharedResource sharedResource) { this.name = name; this.lock = lock; this.sharedResource = sharedResource; } @Override public void run() { System.out.println(name + ": Trying to get lock..."); /* * lock(): Adquiere el bloqueo sobre el monitor y si no puede * pone el Thread actual a dormir hasta que se pueda */ lock.lock(); System.out.println(name + ": Lock acquired"); // Usamos el recurso compartido pero estamos tranquilo que solo nosotros lo tenemos sharedResource.increment(); System.out.println(name + " incrementa contador: " + sharedResource.getCounter()); try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { // Log and Handle exception e.printStackTrace(); } finally { System.out.println(name + ": Release lock"); // Liberamos el recurso lock.unlock(); } } } private static final class SharedResource { private int counter = 0; public void increment() { counter++; } public int getCounter(){ return counter; } } }