首页 > 解决方案 > 为什么生产者-消费者代码不起作用?

问题描述

我正在尝试在信号量的帮助下编写生产者-消费者问题的解决方案。下面是我编写的代码,在执行时它在生成一个数字后卡住了。

我已经检查了信号量的分配,它看起来很好。调用的获取和释放方法的顺序看起来也是正确的。

public class Q {
    int n;
    Semaphore consumerSem = new Semaphore(0);
    Semaphore producerSem = new Semaphore(1);

    synchronized void get(){
        try {
            consumerSem.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Got Data : " + n);
        producerSem.release();
    }

    synchronized void put(int n){
        try {
            producerSem.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Putting Data : " + n);
        this.n=n;
        consumerSem.release();
    }
}

 public class Producer implements Runnable{
   Q q;

    Producer(Q q){
        this.q = q;
    }

    @Override
    public void run() {
        for (int i=0; i<20;i++){
            q.put(i);
        }
    }
}

public class Consumer implements Runnable{
    Q q;

    Consumer(Q q){
        this.q = q;
    }


    @Override
    public void run() {
           for (int i =0;i<20;i++){
               q.get();
           }
    }
}

public class PCRun {

    public static void main(String[] args) {
        Q q = new Q();
        new Thread(new Producer(q),"Producer").start();
        new Thread(new Consumer(q),"Consumer").start();
    }
}

标签: javamultithreadingsemaphoreproducer-consumer

解决方案


你已经做了getput synchronized。所以生产者进入,锁定q,使用一个许可,producerSem并在下一次put调用时阻塞。不幸的是,q仍然被生产者锁定,因此消费者将无法进入get。要解决此问题,请删除两个synchronizeds。

现在要同步对 的访问nsynchronized仅使用访问的地方 n,而不是整个方法。

    int n;
    final Semaphore consumerSem = new Semaphore(0);
    final Semaphore producerSem = new Semaphore(1);

    void get() {
        try {
            consumerSem.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (this) {
            System.out.println("Got Data : " + n);
        }
        producerSem.release();
    }

    void put(int n) {
        try {
            producerSem.acquire();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (this) { // invariant print + write, atomic
            System.out.println("Putting Data : " + n);
            this.n = n;
        }
        consumerSem.release();
    }

推荐阅读