¿Cómo usar bloqueos en el programa Java de subprocesos múltiples?

Un bloqueo puede ser un mecanismo de sincronización de subprocesos más flexible y complicado que el bloque sincronizado estándar. Un candado puede ser una herramienta para controlar el acceso a un recurso compartido por varios subprocesos. Por lo general, un bloqueo proporciona acceso exclusivo a un recurso compartido: solo un subproceso a la vez puede adquirir el bloqueo y todos los que acceden al recurso compartido requieren que el bloqueo se adquiera primero. Sin embargo, algunos bloqueos pueden permitir el acceso simultáneo a un recurso compartido, como el bloqueo de lectura de un ReadWriteLock.

// Example of lock interface
Lock lock = new ReentrantLock();
lock.lock();
 
// critical section 
lock.unlock();

Métodos en la interfaz de bloqueo

Hay ciertos métodos en una interfaz de bloqueo. Vamos a ver esos junto con sus modificadores:

MODIFICADORES DESCRIPCIÓN
vacío lock() – Adquiere el bloqueo si está disponible; si el bloqueo no está disponible, un hilo se bloquea hasta que se libera el bloqueo
lockInterruptably() – Es similar a lock() pero adquiere el bloqueo a menos que se interrumpa el hilo
unlock() – Como sugiere el nombre, simplemente libera la instancia de bloqueo
condición newCondition(): simplemente devuelve la nueva instancia de condición
booleano tryLock(): intenta acumular el bloqueo inmediatamente, devuelve verdadero si el bloqueo tiene éxito
tryLock(largo tiempo, unidad TimeUnit) – A menudo es casi como tryLock(), excepto que espera el tiempo de espera antes de abandonar el intento de acumular el bloqueo.

Implementación de bloqueos

Veamos cómo podemos implementar algunos bloqueos en Java:

1.readWriteLock()

ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

readWriteLock.readLock().lock();

    // ....
    
    
                ......//

readWriteLock.readLock().unlock();


readWriteLock.writeLock().lock();

    // only one writer can enter this section,
    // and only if no threads are currently reading.

readWriteLock.writeLock().unlock();

A continuación se muestra la implementación del método readWriteLock():

Java

// Implementation of ReadWriteLock in Java
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class GFG<O> {
  
    private final ReadWriteLock readWriteLock
        = new ReentrantReadWriteLock();
    private final Lock writeLock
        = readWriteLock.writeLock();
    private final Lock readLock = readWriteLock.readLock();
    private final List<O> list = new ArrayList<>();
  
    // setElement function sets
    // i.e., write the element to the thread
    public void setElement(O o)
    {
        // acquire the thread for writing
        writeLock.lock();
        try {
            list.add(o);
            System.out.println(
                "Element by thread "
                + Thread.currentThread().getName()
                + " is added");
        }
        finally {
            // To unlock the acquired write thread
            writeLock.unlock();
        }
    }
  
    // getElement function prints
    // i.e., read the element from the thread
    public O getElement(int i)
    {
        // acquire the thread for reading
        readLock.lock();
        try {
            System.out.println(
                "Elements by thread "
                + Thread.currentThread().getName()
                + " is printed");
            return list.get(i);
        }
        finally {
            // To unlock the acquired read thread
            readLock.unlock();
        }
    }
    public static void main(String[] args)
    {
        GFG<String> gfg = new GFG<>();
  
        gfg.setElement("Hi");
        gfg.setElement("Hey");
        gfg.setElement("Hello");
  
        System.out.println("Printing the last element : "
                           + gfg.getElement(2));
    }
}
Producción

Element by thread main is added
Element by thread main is added
Element by thread main is added
Elements by thread main is printed
Printing the last element : Hello

2. Bloqueo reentrante()

public class lockImplement {
    //...
    ReentrantLock lock = new ReentrantLock();
    int counter = 0;

    public void testing() {
        lock.lock();
        try {
            // Critical section here
            count++;
        } finally {
            lock.unlock();
        }
    }
    //...
}

A continuación se muestra la implementación del método reentrantLock():

Java

// Java code to illustrate Reentrant Locks
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
  
class worker implements Runnable {
    String name;
    ReentrantLock re;
    public worker(ReentrantLock rl, String n)
    {
        re = rl;
        name = n;
    }
    public void run()
    {
        boolean done = false;
        while (!done) {
            // Getting Outer Lock
            boolean ans = re.tryLock();
  
            // Returns True if lock is free
            if (ans) {
                try {
                    Date d = new Date();
                    SimpleDateFormat ft
                        = new SimpleDateFormat("hh:mm:ss");
                    System.out.println(
                        "task name - " + name
                        + " outer lock acquired at "
                        + ft.format(d)
                        + " Doing outer work");
                    Thread.sleep(1500);
  
                    // Getting Inner Lock
                    re.lock();
                    try {
                        d = new Date();
                        ft = new SimpleDateFormat(
                            "hh:mm:ss");
                        System.out.println(
                            "task name - " + name
                            + " inner lock acquired at "
                            + ft.format(d)
                            + " Doing inner work");
                        System.out.println(
                            "Lock Hold Count - "
                            + re.getHoldCount());
                        Thread.sleep(1500);
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    finally {
                        // Inner lock release
                        System.out.println(
                            "task name - " + name
                            + " releasing inner lock");
  
                        re.unlock();
                    }
                    System.out.println("Lock Hold Count - "
                                       + re.getHoldCount());
                    System.out.println("task name - " + name
                                       + " work done");
  
                    done = true;
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally {
                    // Outer lock release
                    System.out.println(
                        "task name - " + name
                        + " releasing outer lock");
  
                    re.unlock();
                    System.out.println("Lock Hold Count - "
                                       + re.getHoldCount());
                }
            }
            else {
                System.out.println("task name - " + name
                                   + " waiting for lock");
                try {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  
public class test {
    static final int MAX_T = 2;
    public static void main(String[] args)
    {
        ReentrantLock rel = new ReentrantLock();
        ExecutorService pool
            = Executors.newFixedThreadPool(MAX_T);
        Runnable w1 = new worker(rel, "Job1");
        Runnable w2 = new worker(rel, "Job2");
        Runnable w3 = new worker(rel, "Job3");
        Runnable w4 = new worker(rel, "Job4");
        pool.execute(w1);
        pool.execute(w2);
        pool.execute(w3);
        pool.execute(w4);
        pool.shutdown();
    }
}

Producción:

task name - Job2 waiting for lock
task name - Job1 outer lock acquired at 09:49:42 Doing outer work
task name - Job2 waiting for lock
task name - Job1 inner lock acquired at 09:49:44 Doing inner work
Lock Hold Count - 2
task name - Job2 waiting for lock
task name - Job2 waiting for lock
task name - Job1 releasing inner lock
Lock Hold Count - 1
task name - Job1 work done
task name - Job1 releasing outer lock
Lock Hold Count - 0
task name - Job3 outer lock acquired at 09:49:45 Doing outer work
task name - Job2 waiting for lock
task name - Job3 inner lock acquired at 09:49:47 Doing inner work
Lock Hold Count - 2
task name - Job2 waiting for lock
task name - Job2 waiting for lock
task name - Job3 releasing inner lock
Lock Hold Count - 1
task name - Job3 work done
task name - Job3 releasing outer lock
Lock Hold Count - 0
task name - Job4 outer lock acquired at 09:49:48 Doing outer work
task name - Job2 waiting for lock
task name - Job4 inner lock acquired at 09:49:50 Doing inner work
Lock Hold Count - 2
task name - Job2 waiting for lock
task name - Job2 waiting for lock
task name - Job4 releasing inner lock
Lock Hold Count - 1
task name - Job4 work done
task name - Job4 releasing outer lock
Lock Hold Count - 0
task name - Job2 outer lock acquired at 09:49:52 Doing outer work
task name - Job2 inner lock acquired at 09:49:53 Doing inner work
Lock Hold Count - 2
task name - Job2 releasing inner lock
Lock Hold Count - 1
task name - Job2 work done
task name - Job2 releasing outer lock
Lock Hold Count - 0

Nota: Es posible que el programa no funcione en un IDE en línea debido a la llamada de suspensión.

Publicación traducida automáticamente

Artículo escrito por mayanktyagi1709 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *