Falso problema de despertar de esperar y notificar en Java

Prólogo

Este blog es de  https://www.cnblogs.com/clover-forever/p/12616869.html

Escríbalo aquí para su posterior revisión.

El concepto de estela falsa

La documentación oficial de jdk explica:

 

 

 

Entonces, cuando la espera y la notificación se usan juntas, si usa if como condición, habrá falsos despertadores, por lo que debe usar while como condición de bucle . Aquí hay un ejemplo de experimento:

Primero, cree una clase de recurso: (En el subprocesamiento múltiple, las clases de recurso y las operaciones de subproceso generalmente se desacoplan, no en la misma clase, solo cuando el subproceso opera en la clase de recurso, se creará el objeto de la clase de recurso)

package com.test; 

/ **
* clase de recursos
* @author Huxudong
* @createTime 2020-04-01 21:57:39
** /
public class Resource {
/ ** número de producto * /
private int product = 0;

/ * * Compra * /
public sync void get () {
if (product> = 10) {
System.out.println (Thread.currentThread (). GetName () + ":" + "¡El producto está lleno!");
/ ** Cuando el producto está lleno, el hilo de compra se cuelga * /
try {
this.wait ();
} catch (InterruptedException e) {
e.printStackTrace ();
}
}

/ ** compra * /
System.out.println (Thread.currentThread (). GetName () + ":" + ++ product);
/ ** reactivar otros subprocesos * /
this.notifyAll ();

}

/ ** venta * /
vacío público sincronizado sale () {
if (product <= 0) {
System.out.println (Thread.currentThread (). getName () + ":" + "el producto está vacío");
intente {
this.wait ();
} catch ( InterruptedException e) {
e.printStackTrace ();
}
}

/ ** Ventas * /
System.out.println (Thread.currentThread (). GetName () + ":" + --product);
/ ** Despierta otros hilos * /
this.notify ();
}
}

Luego, cree un hilo para operar nuestra clase de recursos (creado directamente a través de la nueva característica de java8, expresión Lambda)

package com.test; 

import java.util.concurrent.TimeUnit;

/ **
* Clase de recurso de operación de subproceso para lograr el desacoplamiento de subproceso y clase de recurso
* @author Huxudong
* @createTime 2020-04-01 23:13:54
** /
public class TestPc {
public static void main (String [] args) {
Resource resource = new Resource ();
new Thread (() -> {
for (int i = 0; i <20; i ++) {
try {
/ * * Dormir para una fácil observación * /
TimeUnit.SECONDS.sleep (2);
} catch (InterruptedException e) {
e.printStackTrace ();
}
resource.get ();
}
}, "Productor A"). Start ();



new Thread (() -> {
for (int i = 0; i <20; i ++) {
resource.sale ();
}

}, "Consumer C") .start ();

new Thread (() -> {
for (int i = 0; i <20; i ++) {

resource.get ();
}

}, "productor B"). start ();

new Thread ( () -> {
for (int i = 0; i <20; i ++) {
resource.sale ();
}

}, "Consumer D"). start ();
}
}

Echemos un vistazo primero Que paso:

 

 

Sí, leíste bien, ¿cómo podría haber números negativos? Esto definitivamente está mal. Calmarse y analizar, aún un poco pista, saber dónde ocurrió el problema (entonces eres una persona que no está sorprendida, muy poderosa).

Analicémoslo. Al principio, los hilos C y D del consumidor se llamaban (porque escribimos dormir en el productor). El consumidor descubrió que el recurso del producto era 0 en este momento, por lo que el consumidor C y D Hermano, no hay forma de llamar al método de espera, dormir y liberar el bloqueo.

Pero en este momento, el primer consumidor se ha despertado, el motor ha comenzado a producir productos y, después de la producción, todos los hilos de consumo en espera se han despertado. Los dos hermanos C y D finalmente se despertaron, y D primero obtuvo la cerradura, por lo que primero consumieron un producto, luego descubrieron que no había producto y se fueron a dormir con tristeza, pero no lo olviden en este momento. Se despertó un amigo C. Usted despertó a otros. ¿Qué más hicieron? De lo contrario, es muy incómodo. Desafortunadamente, la condición de juicio en este momento es si. Restricciones condicionales, seguidas de la ejecución del código de dormir anterior, decidieron decididamente consumir otro producto. Resulta que después de que D buddy consume, ya es 0. Este amigo C irá a consumir menos uno, ¿es -1? Y así sucesivamente. Se encuentra que si las condiciones de juicio no son buenas, el amigo C despertado en este momento es equivalente a un falso despertar, lo que traerá errores impredecibles al programa. Por lo tanto, es necesario usar while mientras se juzga aquí, primero mire el resultado de reemplazar si por while.

 Esta vez, el resultado es más normal, ¿por qué usarlo mientras, porque, como se mencionó anteriormente, incluso si todos los hilos del consumidor están despiertos, el ciclo while continuará juzgando en este momento, si la condición es 0 en este momento, entonces C El amigo no puede salir mientras, entonces no volverá y ejecutará la siguiente operación de reducción de productos de consumo, entonces se evitará este error. Esto también se recomienda oficialmente cuando se usa esperar y notificar a todos, debe usar el juicio de condición del bucle while.

Supongo que te gusta

Origin www.cnblogs.com/jichi/p/12694260.html
Recomendado
Clasificación