多线程生产者与消费者模型?

多线程生产者与消费者模型

生产者与消费者模型,通过Object的wait()以及notifyAll()方法实现以及同步方法实现

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)


class Resource {
    private int num = 0;
    private boolean flag = true;
    // flag为true可以执行加法操作,不可以执行减法操作
    // flag为false可以执行减法操作,不可以执行加法操作
    public synchronized void add() throws Exception {
       if(!this.flag) { // flag为false只能执行减法操作
           super.wait(); // 需要等待
       }
       //Thread.sleep(100);
        this.num++;
        System.out.println(Thread.currentThread().getName() + "运行, num = " + this.num);
        this.flag = false; // 可以进行减法操作
        super.notifyAll(); // 唤醒其他线程
    }
    public synchronized void sub() throws Exception {
        if(this.flag) { // flag为true只能进行加法操作,减法操作需要等待
            super.wait();
        }
       // Thread.sleep(100);
        this.num--;
        System.out.println(Thread.currentThread().getName() + "运行, num = " + this.num);
        this.flag = true    ; // 可以进行加法操作
        super.notifyAll(); // 唤醒其他线程
    }
}

class AddThread implements Runnable {
    private Resource res;

    public AddThread(Resource res) {
        this.res = res;
    }
    @Override
    public void run() {
        for (int i = 0 ; i < 50 ; i++) {
            try {
                this.res.add();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

class SubThread implements Runnable {
    private Resource res;

    public SubThread(Resource res) {
        this.res = res;
    }

    @Override
    public void run() {
        for (int i = 0 ; i < 50 ; i++) {
            try {
                this.res.sub();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadDemo {
    public static void main(String[] args) {
        Resource res = new Resource();
        AddThread at = new AddThread(res);
        SubThread st = new SubThread(res);

        new Thread(at, "加法操作-1").start();
        new Thread(at, "加法操作-2").start();

        new Thread(st, "减法操作-1").start();
        new Thread(st, "减法操作-2").start();
    }
}

我期待他加完只能减,减完只能加.而现在输出的不对,他会小于0

阅读 2.2k
2 个回答

问题出在,你有两个加线程和两个减线程。然后你有选择用 notifyAll 的方式去唤醒它们。

在加线程中使用 notifyAll 的方式唤醒等待的线程,所有的两个减线程都会被唤醒。这两个减线程不会同时运行(因为 synchronized),但是他们会先后运行。

减线程被唤醒后,也就是 wait() 返回之后,sub() 没有继续检查 flag 的值(注意,wait()if (this.flag) 里,不是 while),而是直接修改了 numflag

这样,两个被唤醒的减线程,都会去修改 numflag 。从而 num 自减了两次。

(被唤醒的第二个减线程运行的时候,flag 已经变为了 true 。但是由于 wait() 返回之后没有对 flag 的判断,还是去修改了 num 。)

wait会释放锁呀,两个加或者两个减会同时进入到wait状态,此时notifyall会同时唤醒,且不会再判断flag的值

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题