【问题标题】:Issue with Producer-Consumer using Lock and Condition使用锁和条件的生产者-消费者问题
【发布时间】:2016-09-13 17:42:24
【问题描述】:

我已经使用 ReentrantLock 和 Condition 实现了 Producer-Consumer 程序。如果我先启动 Producer 线程,我的实现运行不会出现任何错误。但是如果我首先启动消费者线程,我会得到一个 IllegalMonitorStateException。请指出我的程序有什么问题。

这是我的实现。

public class ProducerConsumerReentrantLock {
    public static void main(String[] args) throws InterruptedException {
        List<Integer> list = new ArrayList<Integer>(10);
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        int limit=10;

        ProductionTaskReentrantLock produce = new ProductionTaskReentrantLock(lock, condition, limit, list);
        ConsumptionTaskReentrantLock consume = new ConsumptionTaskReentrantLock(lock, condition, limit, list);

        Thread productionWorker = new Thread(produce,"Producer");
        Thread consumptionWorker = new Thread(consume,"Consumer");

        consumptionWorker.start();
        productionWorker.start();
//      consumptionWorker.start();

        productionWorker.join();
        consumptionWorker.join();
    }
}

.

class ProductionTaskReentrantLock implements Runnable{

    List<Integer> list = null;
    ReentrantLock lock;
    Condition condition;
    int limit;

    public ProductionTaskReentrantLock(ReentrantLock lock, Condition condition, int limit, List<Integer> list) {
        super();
        this.lock = lock;
        this.condition = condition;
        this.limit = limit;
        this.list = list;
    }

    @Override
    public void run() {
        lock.lock();
        try{
            for (int i = 0; i < 10 ; i++) {
                while(list.size()==limit){
                    try {
                        System.out.println("List is full");
                        condition.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Produced "+i);
                list.add(i);
                System.out.println(list);
                condition.signalAll();
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } finally {
            lock.unlock();
        }
    }
}

.

class ConsumptionTaskReentrantLock implements Runnable{

    List<Integer> list = null;
    ReentrantLock lock;
    Condition condition;
    int limit;

    public ConsumptionTaskReentrantLock(ReentrantLock lock, Condition condition, int limit, List<Integer> list) {
        super();
        this.lock = lock;
        this.condition = condition;
        this.limit = limit;
        this.list = list;
    }

    @Override
    public void run() {
        lock.lock();
        try{
            for (int i = 0; i < 10 ; i++) {
                while(list.isEmpty()){
                    try {
                        System.out.println("List is empty");
                        condition.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Consumed "+list.remove(0));
                System.out.println(list);
                condition.signalAll();
            }
        } finally {
            lock.unlock();
        }
    }

}

【问题讨论】:

  • IllegalMonitorStateException - 抛出该异常以指示线程已尝试在对象的监视器上等待或通知其他线程在对象的监视器上等待但不拥有指定的监视器。
  • 我对 Java 线程的了解不够,无法快速找出您的错误,但这是一个非常具有描述性的错误消息
  • 你可以尝试使用 condition.await() 而不是等待,看看是否能解决这个问题?
  • @Kamal:这就是答案。 每个对象都有一个wait()方法——甚至是Condition对象——你不能调用它,除非在那个对象上synchronized

标签: java multithreading concurrency synchronization reentrantlock


【解决方案1】:

请参见下面的类似示例,您应该使用 await 而不是 wait,并使用您已经在做的 ReentrantLock 返回的条件。(请参阅 Java doc for ReeentrantLock):

package reentrant_prodcons;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Reentrant_ProdCons {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here

        Queue<Integer> queue=new LinkedList<Integer>();
        ReentrantLock lock=new ReentrantLock();
        Condition con=lock.newCondition();
        final int size = 5;

        new Producer(lock, con, queue, size).start();
        new Consumer(lock, con, queue).start();

    }

}


class Producer extends Thread{

    ReentrantLock  lock;
    Condition con;
    Queue<Integer> queue;
    int size;

    public Producer(ReentrantLock lock, Condition con, Queue<Integer> queue, int size) {
        this.lock = lock;
        this.con = con;
        this.queue = queue;
        this.size=size;
    }


    public void run(){
        for(int i=0;i<10;i++){
            lock.lock();
            while(queue.size()==size){
                try {
                    con.await();
                } catch (InterruptedException ex) {
                    Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            queue.add(i);
            System.out.println("Produced : "+i);
            con.signal();
            lock.unlock();
        }
    }

}

class Consumer extends Thread{


    ReentrantLock lock;
    Condition con;
    Queue<Integer> queue;


    public Consumer(ReentrantLock lock, Condition con, Queue<Integer> queue) {
        this.lock = lock;
        this.con = con;
        this.queue = queue;
    }

    public void run(){
        for(int i=0;i<10;i++){
           lock.lock();
           while(queue.size()<1){
               try {
                   con.await();
               } catch (InterruptedException ex) {
                   Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
               }
           }
            System.out.println("Consumed : "+queue.remove());
            con.signal();
            lock.unlock();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    相关资源
    最近更新 更多