微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么生产者-消费者代码不起作用?

如何解决为什么生产者-消费者代码不起作用?

我正在尝试通过信号量来编写生产者-消费者问题的解决方案。 下面是我编写的代码,在执行时会产生一个数字而卡住。

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

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

解决方法

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

现在要在n上同步访问,仅在访问{em> synchronized的地方使用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();
    }
,

不是使用2个信号量,而是仅使用1个。n的值最终将在2个线程之间共享,因此它是唯一需要同步的东西,因为信号量本质上是线程安全的。

    public static class Q {

        int n;

        Semaphore available = new Semaphore(0);

        void get() throws InterruptedException {
            available.acquire();
            synchronized (this) {
                System.out.printf("Get %s\n",n));
            }
        }

        void put(int n){
            available.release();
            synchronized (this) {
                System.out.printf("Put %s\n",n);
                this.n = n;
            }
        }
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。