Java等待通知与共享整数对象

标签 java multithreading atomic

我正在尝试使用跨多个线程的共享整数对象按顺序打印从 1 到 10 的数字。当使用共享对象作为 AtomicInteger 时,程序可以正常工作,但是当使用普通 Integer 对象时,程序会抛出异常,我不知道为什么会发生这种情况。

使用 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();  
        }  
      }  
    }  
  }  
}  

输出

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

使用普通 Integer 对象进行编程

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();
        }
      }
    }
  }
}

输出

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)

最佳答案

this.sharedObject++;没有做你想象的那样。

Integer是不可变的,它不能改变现有的共享对象。此操作的作用是将值拆箱到 int 中。 ,递增它,然后将其装回到不同的 Integer 中实例。

所以您的代码(几乎*)相当于以下内容:

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

此时您的对象不再是同一个实例,您的 synchronized block 不会与 wait() 对齐/notify()来电。

请注意,这与 AtomicInteger 的原子性无关。 ,这只是与 ++ 的方式有关。运算符(operator)在 Integer 上工作.

*实际上,您可能会获得缓存的实例,而不是 new Integer() ,但它仍然是一个不同的实例,因为它代表不同的 int值。

关于Java等待通知与共享整数对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54923495/

相关文章:

Java SSL套接字 : How to send full server cert chain?

java - Java 空 Optional 的类型是什么?

java - 有条件地加载应用程序上下文

c++ - 这个 RAII 独占资源检查对象/管理器组合线程安全吗?

Python TCP 几个同时监听多个端口

c++ - 使用 std::atomic 实现无锁结构,Dtor 崩溃

java - 如何在java中获取HttpURLConnection使用的套接字

c++ - STLR(B) 是否在 ARM64 上提供顺序一致性?

c++ - Openmp 原子和关键

java - Thread.sleep() 与 java 中的同步