为什么我在 Java 中使用锁和条件在这个生产者-消费者中遇到死锁?

Why am I getting a deadlock in this producer-consumer in Java using locks and conditions?

我是 Java 的新手,我正在尝试学习 Java 并发。我已经为生产者-消费者问题(单一生产者和消费者)编写了一个简单的代码。似乎存在死锁,因为当数据可用时消费者没有得到通知。任何人都可以查看代码吗?

import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.locks.*;

class ThreadFactory implements Runnable{
    List<String> list = new ArrayList<>();
    Thread prThread;
    final Lock lock = new ReentrantLock();
    final Condition notFull  = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition();
    final int CAPACITY = 10;

    public enum Role{
    PRODUCER,
    CONSUMER
    };

    Role role;
    public int i = 0;

    private void produce() throws InterruptedException {
        while(true){
            lock.lock();
            try{
                while(list.size()  == CAPACITY){
                    System.out.println("List is full to its CAPACITY, waiting");
                    notEmpty.await();
                }
                String str = "Data " + i++;
                System.out.println("Putting " + str + " to list");
                list.add(str);
                notFull.signalAll();
            }
            finally{
                lock.unlock();
                Thread.sleep(500);
            }
        }
    }

    private void consume() throws InterruptedException{
        while(true){
            lock.lock();
            try{
                while(list.size() == 0){
                    System.out.println("List is empty, waiting");
                    notFull.await();
                }
                String str = list.remove(list.size()-1);
                System.out.println("Popping " + str + " from list");
                notEmpty.signal();
            }
            finally{
                lock.unlock();
            }
        }
    }

    public void run(){
        System.out.println("Starting thread " + prThread.getName());
        try{
            if(role == Role.PRODUCER){
                produce();
            }           
            else if(role == Role.CONSUMER){
                consume();
            }
        }
        catch(InterruptedException e){
            System.out.println("Thread interrupted");
        }
    }

    public ThreadFactory(List<String> l, int role, String name){
        this.list = l;
        prThread = new Thread(this, name);
        if(role == 0)
            this.role = Role.PRODUCER;
        else
            this.role = Role.CONSUMER;
        prThread.start();
    }
}

public class ProducerConsumer{
    public static void main(String[] args){
        List<String> l = new ArrayList<>();
        ThreadFactory c = new ThreadFactory(l,1, "Consumer");
        ThreadFactory p = new ThreadFactory(l,0, "Producer");
    }
}

好吧,我不确定发生了什么,可能是因为您正在 运行同时生产 consume()produce ()方法在classThreadFactory的方法运行()中。

我要做的是为消费者创建一个 class,为生产者创建另一个,两个 class 扩展 class 线程。然后我将在它们各自的 classes.

的 运行() 中调用 consume() 和 producer()
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class ThreadFactory {
    List<String> list = new ArrayList<>();
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition();
    final int CAPACITY = 10;

    public int i = 0;

    class Producer extends Thread {

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

    class Consumer extends Thread {

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

    private void produce() throws InterruptedException {
        System.out.println("Starting thread " + Thread.currentThread().getName());
        while (true) {
            lock.lock();
            try {
                while (list.size() == CAPACITY) {
                    System.out.println("List is full to its CAPACITY, producer waiting");
                    notFull.await();
                }
                if (i == CAPACITY) i=0;
                String str = "Data " + i++;
                System.out.println("Putting " + str + " to list of size "+list.size());
                list.add(str);
                if (list.size() ==1 )
                    notEmpty.signal();
            } finally {
                lock.unlock();
                Thread.sleep(500);
            }
        }
    }

    private void consume() throws InterruptedException {
        System.out.println("Starting thread " + Thread.currentThread().getName());
        while (true) {
            lock.lock();
            try {
                while (list.size() == 0) {
                    System.out.println("List is empty, consumer waiting");
                    notEmpty.await();
                }
                String str = list.remove(list.size() - 1);
                System.out.println("Popping " + str + " from list of size "+list.size());
                if (list.size() ==CAPACITY-1 )
                    notFull.signal();
            } finally {
                lock.unlock();
            }
        }
    }

    public ThreadFactory(List<String> l ){
        this.list = l;
        Thread p= new Producer();
        p.setName("Producer");
        p.start();
        Thread c=new Consumer();
        c.setName("Consumer");
        c.start();
    }
}

public class ProducerConsumer {
    public static void main(String[] args) {
        List<String> l = new ArrayList<>();
        ThreadFactory pc = new ThreadFactory(l);
    }
}

希望对您有所帮助。

这不是死锁,锁是每个 class 的实例成员,其中每个可运行实例都创建自己的锁。你的生产者和消费者使用他们自己的锁,所以他们看不到彼此的信号,他们永远等待。他们应该使用同一把锁。