java - 在 Java 中使用 wait() 和 notify() 被阻止

标签 java multithreading synchronized producer-consumer

我正在使用 Java 中的 wait()notify() 编写生产者和消费者代码。 Thread-0 创建并在 produce() 上调用,Thread-1 创建并在 consume() 上调用。

public class Processor {

  private volatile List<Integer> list = new ArrayList<>();
  private final int MAX_CAPACITY = 5;
  Object lock = new Object();

  public void produce() throws InterruptedException {

    while (true) {

      while (list.size() == MAX_CAPACITY) {
        System.out.println("List is full! Producer is Waiting....");
        synchronized (lock) {
          lock.wait();
        }
      }

      synchronized (lock) {
        int random = new Random().nextInt(100);
        list.add(random);
        System.out.println("Added to list:" + random);
        lock.notify();
      }
    }
  }

  public void consume() throws InterruptedException {

    while (true) {

      while (list.size() == 0) {
        System.out.println("List is empty!! Consumer is Waiting...");
        synchronized (lock) {
          lock.wait();
        }
      }

      synchronized (lock) {
        int i = list.remove(0);
        System.out.println("Removed from list:" + i);
        lock.notify();
      }
    }
  }
}

问题是在执行过程中,程序在 produce() 之后停止:

List is empty!! Consumer is Waiting...
Added to list:22
Added to list:45
Added to list:72
Added to list:91
Added to list:51
List is full! Producer is Waiting....

我不明白这里有什么问题。我不知何故发现将 while 循环中的代码包装在 produce()consume() 中的 synchronized block 中解决问题。

生产()

synchronized (lock) {
                while (list.size() == MAX_CAPACITY) {
                    System.out.println("List is full! Producer is Waiting....");

                    lock.wait();
                }

消费

synchronized (lock) {
                while (list.size() == 0) {
                    System.out.println("List is empty!! Consumer is Waiting...");

                    lock.wait();
                }
            }

这里有什么问题?是线程饥饿还是死锁?

编辑:调用类:

public class App {
    public static void main(String[] args) {
        final Processor processor = new Processor();

        Runnable r1 = new Runnable() {

            @Override
            public void run() {
                try {
                    processor.produce();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };

        Runnable r2 = new Runnable() {

            @Override
            public void run() {
                try {
                    processor.consume();
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
            }
        };

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);

        t1.start();
        t2.start();


    }
}

最佳答案

当您执行 list.size() 时,它不是线程安全的,并且无法保证您会在另一个线程中看到该值发生更改。如果 JIT 检测到您没有在该线程中更改它,它甚至可以内联该值。

通过将 synchronized block 放在循环之外,您可以确保值的更改是可见的(因为它也在 while(true) 循环内)。

关于java - 在 Java 中使用 wait() 和 notify() 被阻止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38498930/

相关文章:

java - 如何使用日期正则表达式的模式匹配器?

Java 发生之前澄清以及如何在两个线程之间安全地来回传递对象

java - AtomicInteger.incrementAndGet 线程安全吗?

java - 在java中处理套接字

java - maven 依赖项 - 哪个依赖项使用不需要的 jar?

java - 合并到两个排序的 Java 链表的最有效方法(非自定义链表)

java - 同步 Collection 列表

java - 我们可以对每个条目使用 Synchronized 而不是 ConcurrentHashMap 吗?

java - 无法选中复选框

Java线程级沙箱