Concurrencia Java - Interfaz ReadWriteLock

Una interfaz java.util.concurrent.locks.ReadWriteLock permite que se lean varios subprocesos a la vez, pero solo un subproceso puede escribir a la vez.

  • Read Lock - Si ningún subproceso ha bloqueado ReadWriteLock para escritura, entonces varios subprocesos pueden acceder al bloqueo de lectura.

  • Write Lock - Si ningún hilo está leyendo o escribiendo, entonces un hilo puede acceder al bloqueo de escritura.

Métodos de bloqueo

A continuación se muestra la lista de métodos importantes disponibles en la clase Lock.

No Señor. Método y descripción
1

public Lock readLock()

Devuelve el candado utilizado para la lectura.

2

public Lock writeLock()

Devuelve el candado utilizado para escribir.

Ejemplo

El siguiente programa TestThread demuestra estos métodos de la interfaz ReadWriteLock. Aquí hemos usado readlock () para adquirir el bloqueo de lectura y writeLock () para adquirir el bloqueo de escritura.

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestThread {
   private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
   private static String message = "a";

   public static void main(String[] args) throws InterruptedException {
      Thread t1 = new Thread(new WriterA());
      t1.setName("Writer A");
      
      Thread t2 = new Thread(new WriterB());
      t2.setName("Writer B");
      
      Thread t3 = new Thread(new Reader());
      t3.setName("Reader");
      t1.start();
      t2.start();
      t3.start();
      t1.join();
      t2.join();
      t3.join();
   }

   static class Reader implements Runnable {

      public void run() {
         
         if(lock.isWriteLocked()) {
            System.out.println("Write Lock Present.");
         }
         lock.readLock().lock();

         try {
            Long duration = (long) (Math.random() * 10000);
            System.out.println(Thread.currentThread().getName() 
               + "  Time Taken " + (duration / 1000) + " seconds.");
            Thread.sleep(duration);
         } catch (InterruptedException e) {
            e.printStackTrace();
         } finally {
            System.out.println(Thread.currentThread().getName() +": "+ message );
            lock.readLock().unlock();
         }
      }
   }

   static class WriterA implements Runnable {

      public void run() {
         lock.writeLock().lock();
         
         try {
            Long duration = (long) (Math.random() * 10000);
            System.out.println(Thread.currentThread().getName() 
               + "  Time Taken " + (duration / 1000) + " seconds.");
            Thread.sleep(duration);
         } catch (InterruptedException e) {
            e.printStackTrace();
         } finally {
            message = message.concat("a");
            lock.writeLock().unlock();
         }
      }
   }

   static class WriterB implements Runnable {

      public void run() {
         lock.writeLock().lock();
         
         try {
            Long duration = (long) (Math.random() * 10000);
            System.out.println(Thread.currentThread().getName() 
               + "  Time Taken " + (duration / 1000) + " seconds.");
            Thread.sleep(duration);
         } catch (InterruptedException e) {
            e.printStackTrace();
         } finally {
            message = message.concat("b");
            lock.writeLock().unlock();
         }
      }
   }
}

Esto producirá el siguiente resultado.

Salida

Writer A  Time Taken 6 seconds.
Write Lock Present.
Writer B  Time Taken 2 seconds.
Reader  Time Taken 0 seconds.
Reader: aab