Java espera notificar con objeto entero compartida

user3157908:

Estoy tratando de imprimir los números del 1 al 10 en la secuencia utilizando un objeto entero compartida a través de varios subprocesos. Cuando se utiliza el objeto compartido como AtomicInteger, el programa funciona correctamente, pero al usar objetos normales entero, el programa lanza una excepción y no sé por qué ocurre esto.

Programa con AtomicInteger

import java.util.concurrent.atomic.AtomicInteger;  

public class ThreadingProblem {

  public static void main(String[] args) {  
    AtomicInteger sharedInt = new AtomicInteger(0);  
    Thread t1 = new Thread(new ThreadingPrintingTask(sharedInt), "PrinterThread");  
    Thread t2 = new Thread(new ThreadingIncrementingTask(sharedInt), "IncrementerThread");  
    t1.start();  
    t2.start();  
  }  
}  

class ThreadingPrintingTask implements Runnable {    

  private AtomicInteger sharedObject;  

  public ThreadingPrintingTask(AtomicInteger sharedObject) {  
    this.sharedObject = sharedObject;  
  }  

  @Override  
  public void run() {  
    try {  
      synchronized (sharedObject) {  
        while (true) {  
          sharedObject.wait();  
          System.out.println("Shared object value is: " + sharedObject);  
          sharedObject.notify();  
        }  
      }  
    }  
    catch (InterruptedException e) {  
    }  

  }  
}  

class ThreadingIncrementingTask implements Runnable {  

  private AtomicInteger sharedObject;  

  public ThreadingIncrementingTask(AtomicInteger sharedObject) {  
    this.sharedObject = sharedObject;  
  }  

  @Override  
  public void run() {  
    synchronized (sharedObject) {  
      while (this.sharedObject.get() < 10) {  
        this.sharedObject.incrementAndGet();  
        this.sharedObject.notify();  
        try {  
          this.sharedObject.wait();  
        }  
        catch (InterruptedException e) {  
          // TODO Auto-generated catch block  
          e.printStackTrace();  
        }  
      }  
    }  
  }  
}  

Salida

Shared object value is: 1
Shared object value is: 2
Shared object value is: 3
Shared object value is: 4
Shared object value is: 5
Shared object value is: 6
Shared object value is: 7
Shared object value is: 8
Shared object value is: 9
Shared object value is: 10

Programa con objeto de enteros normales

public class ThreadingProblem {

  public static void main(String[] args) {
    Integer sharedInt = new Integer(0);
    Thread t1 = new Thread(new ThreadingPrintingTask(sharedInt), "PrinterThread");
    Thread t2 = new Thread(new ThreadingIncrementingTask(sharedInt), "IncrementerThread");
    t1.start();
    t2.start();
  }
}

class ThreadingPrintingTask implements Runnable {

  private Integer sharedObject;

  public ThreadingPrintingTask(Integer sharedObject) {
    this.sharedObject = sharedObject;
  }

  @Override
  public void run() {
    try {
      synchronized (sharedObject) {
        while (true) {
          sharedObject.wait();
          System.out.println("Shared object value is: " + sharedObject);
          sharedObject.notify();
        }
      }
    }
    catch (InterruptedException e) {
    }

  }
}

class ThreadingIncrementingTask implements Runnable {

  private Integer sharedObject;

  public ThreadingIncrementingTask(Integer sharedObject) {
    this.sharedObject = sharedObject;
  }

  @Override
  public void run() {
    synchronized (sharedObject) {
      while (this.sharedObject < 10) {
        this.sharedObject++;
        this.sharedObject.notify();
        try {
          this.sharedObject.wait();
        }
        catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
  }
}

Salida

Exception in thread "IncrementerThread" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at com.itiviti.apps.catalys.shared.mock.ThreadingIncrementingTask.run(ThreadingProblem.java:52)
    at java.lang.Thread.run(Unknown Source)
biziclop:

this.sharedObject++; no hace lo que supuso que iba a hacer.

Dado que Integeres inmutable, no puede cambiar el objeto compartido existente. Lo que hace esta operación en cambio, es el valor unbox en una int, se incrementará, a continuación, la caja de nuevo en un diferente Integerejemplo.

Por lo que su código es (casi *) equivalente a la siguiente:

int temp = this.sharedObject.intValue();
temp = temp + 1;
this.sharedObject = new Integer(temp);

Como en este punto el objeto ya no es la misma instancia, los synchronizedbloques no se alinean con los wait()/ notify()las llamadas.

Tenga en cuenta que esto no tiene nada que ver con la atomicidad de AtomicInteger, es simplemente que ver con la forma en que el ++operario trabaja en una Integer.

* En realidad, es posible que obtenga una instancia almacenada en caché en lugar de new Integer(), pero todavía habrá una instancia diferente, ya que representa un diferente intvalor.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=223166&siteId=1
Recomendado
Clasificación