¿Qué es la condición deslizada en subprocesos múltiples?

La condición deslizada es un tipo especial de condición de carrera que puede ocurrir en una aplicación multiproceso. En este, un hilo se suspende después de leer una condición y antes de realizar las actividades relacionadas con ella. Raramente ocurre, sin embargo, uno debe buscarlo si el resultado no es el esperado.

Ejemplo : supongamos que hay dos subprocesos A y B que desean procesar una string S. En primer lugar, se inicia el subproceso A , comprueba si quedan más caracteres para procesar, inicialmente toda la string está disponible para su procesamiento, por lo que la condición es verdadera. Ahora, el subproceso A está suspendido y el subproceso B comienza. Vuelve a verificar la condición, que se evalúa como verdadera y luego procesa toda la string S. Ahora, cuando el subproceso A comienza nuevamente la ejecución, la string S se procesa por completo en este momento y, por lo tanto, se produce un error. Esto se conoce como una condición deslizada.

Programa para demostrar condiciones deslizadas en Java

// Java program to demonstrate
// slipped conditions
  
public class Main {
    public static void main(String[] args)
    {
        ReadingThread readingThread
            = new ReadingThread();
        SlippedThread slippedThread
            = new SlippedThread();
  
        slippedThread.start();
        readingThread.start();
    }
}
  
class CommonResource {
    static final String string = "Hello";
    static int pointerPosition = 0;
}
  
// Thread to demonstrate a slipped condition
class SlippedThread extends Thread {
    @Override
    public void run()
    {
        // Check if any characters
        // are left to process
        if (CommonResource.pointerPosition
            != CommonResource.string.length()) {
            System.out.println("Characters left! "
                               + "I can process the string");
  
            // Cause the thread to wait to cause
            // a slipped condition
            try {
                synchronized (this)
                {
                    wait(500);
                }
            }
  
            catch (InterruptedException e) {
                System.out.println(e);
            }
  
            try {
                while (CommonResource.pointerPosition
                       < CommonResource.string.length()) {
  
                    System.out.println("Thread1 "
                                       + CommonResource.string
                                             .charAt(
                                                 CommonResource
                                                     .pointerPosition));
                    CommonResource.pointerPosition++;
                }
            }
  
            catch (StringIndexOutOfBoundsException e) {
                System.out.println("\nNo more character left"
                                   + " to process. This is a"
                                   + " slipped condition");
            }
        }
    }
}
  
// Thread to process the whole String
class ReadingThread extends Thread {
    @Override
    public void run()
    {
        System.out.println("Thread2 trying to "
                           + "process the string");
        while (CommonResource.pointerPosition
               < CommonResource.string.length()) {
  
            System.out.print("Thread2 "
                             + CommonResource.string
                                   .charAt(
                                       CommonResource
                                           .pointerPosition));
            CommonResource.pointerPosition++;
        }
    }
}
Producción:

Characters left! I can process the string
Thread2 trying to process the string
Thread2 H
Thread2 e
Thread2 l
Thread2 l
Thread2 o
No more character left to process. This is a slipped condition

La solución al problema de las condiciones deslizadas es bastante simple y directa . Cualquier recurso al que vaya a acceder un subproceso después de verificar la condición, debe estar bloqueado por el subproceso y solo debe liberarse después de que el subproceso haya realizado el trabajo. Todos los accesos deben estar sincronizados .

Con respecto al problema anterior, las condiciones deslizadas se pueden eliminar bloqueando el objeto String de la clase CommonResource . En este escenario, el subproceso primero obtiene acceso y bloquea la string y luego intenta procesar la string.

Solución al ejemplo anterior

public class Main {
    public static void main(String[] args)
    {
        ReadingThread readingThread
            = new ReadingThread();
        SlippedThread slippedThread
            = new SlippedThread();
  
        slippedThread.start();
        readingThread.start();
    }
}
  
class CommonResource {
  
    static final String string = "Hello";
    static int pointerPosition = 0;
  
    // A static variable added
    // to lock the String object
    static boolean isLocked = false;
}
  
// Thread to demonstrate a slipped condition
class SlippedThread extends Thread {
    @Override
    public void run()
    {
        // Check if any characters
        // are left to process
        if (CommonResource.isLocked
                != true
            && CommonResource.pointerPosition
                   != CommonResource.string.length()) {
  
            System.out.println("Characters left! "
                               + "I can process the string");
            CommonResource.isLocked = true;
  
            // Cause the thread to wait to cause
            // a slipped condition
            try {
                synchronized (this)
                {
                    wait(250);
                }
            }
  
            catch (InterruptedException e) {
                System.out.println(e);
            }
  
            try {
                while (CommonResource.pointerPosition
                       < CommonResource.string.length()) {
  
                    System.out.println("Thread1 "
                                       + CommonResource
                                             .string.charAt(
                                                 CommonResource
                                                     .pointerPosition));
                    CommonResource.pointerPosition++;
                }
            }
  
            catch (StringIndexOutOfBoundsException e) {
                System.out.println("\nNo more character "
                                   + "left to process. This is "
                                   + "a slipped condition");
            }
            CommonResource.isLocked = false;
        }
    }
}
  
// Thread to process the whole String
class ReadingThread extends Thread {
    @Override
    public void run()
    {
        System.out.println("Thread2 trying to"
                           + " process the string");
        if (CommonResource.isLocked == false) {
            CommonResource.isLocked = true;
            synchronized (this)
            {
                while (CommonResource.pointerPosition
                       < CommonResource.string.length()) {
                    System.out.println("Thread2 "
                                       + CommonResource.string
                                             .charAt(
                                                 CommonResource
                                                     .pointerPosition));
                    CommonResource.pointerPosition++;
                }
            }
        }
        CommonResource.isLocked = false;
    }
}

Producción

Characters left! I can process the string
Thread2 trying to process the string
Thread1 H
Thread1 e
Thread1 l
Thread1 l
Thread1 o

En el programa anterior, se agrega un nuevo miembro booleano estático isLocked a la clase CommonResource . Ahora, cada vez que un subproceso intenta procesar la string, primero obtiene el bloqueo y luego lo procesa. En este ejemplo, el subproceso SlippedCondition comprueba si isLocked es falso y si queda una string por procesar. Si es así, obtiene el bloqueo y luego espera y finalmente procesa la string. Mientras tanto, ReadingThread intenta procesar la string, pero no puede, ya que SlippedThread estableció isLocked como verdadero .

Publicación traducida automáticamente

Artículo escrito por CharchitKapoor 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 *