package ar.com.javacuriosities.concurrency.reentrant_read_write_lock; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; /* * La clase ReentrantReadWriteLock se usa cuando queremos tener distintos tipos * de locks para las operaciones de escritura y lectura, o sea puede haber * multiples operaciones de lectura siempre y cuando no se este realizando * ninguna operación de escritura, y la escritura iniciara cuando nadie este leyendo * el recurso */ public class Main { private static final int NUMBER_OF_THREADS = 40; public static void main(String[] args) { // Creamos un Lock de escritura y lectura ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); // Creamos un Pool de 40 Threads ExecutorService executor = Executors .newFixedThreadPool(NUMBER_OF_THREADS); // Ejecutamos distintas tareas for (int i = 1; i <= 10; i++) { executor.execute(new Reader("Reader-" + i, lock.readLock())); } for (int i = 1; i <= 10; i++) { executor.execute(new Writer("Writer-" + i, lock.writeLock())); } for (int i = 1; i <= 10; i++) { executor.execute(new Reader("Reader-" + i, lock.readLock())); } // No aceptamos nuevas tareas executor.shutdown(); while (!executor.isTerminated()) { } } /* * Creamos un Thread que van a ejecutar operaciones de escritura Un solo * escritor puede estar al mismo tiempo. */ private static final class Writer extends Thread { /* * Usamos un WriteLock el cual tiene exclusion mutua para las escrituras * de Write */ private WriteLock lock; public Writer(String name, WriteLock lock) { super(name); this.lock = lock; } @Override public void run() { try { System.out.println(getName() + ": Trying to write"); /* * Al pedir el lock() se va a comprobar que no haya nadie * escribiendo y que tampoco haya ningún lector */ lock.lock(); System.out.println(getName() + ": wrote something"); TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 50)); } catch (InterruptedException e) { // Log and Handle exception e.printStackTrace(); } finally { lock.unlock(); } } } /* * Esta clase representa los lectores, estos puede haber ejecutar lecturas * de forma concurrente pero no pueden leer si un escritor */ private static final class Reader extends Thread { /* * El ReadLock nos deja leer hasta detectar un Writer */ private ReadLock lock; public Reader(String nombre, ReadLock lock) { super(nombre); this.lock = lock; } @Override public void run() { try { System.out.println(getName() + ": Trying to read"); /* * Obtenemos el lock() siempre y cuando no haya nadie escribiendo */ lock.lock(); System.out.println(getName() + ": Read something"); TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 50)); } catch (InterruptedException e) { // Log and Handle exception e.printStackTrace(); } finally { // Liberamos a esta lector lock.unlock(); } } } }