wait()/notify()工作不正常



我有一个ConsumerProducer对象,我想从两个不同的线程获取它的锁。类别如下:

public class ConsumerProducer {
    public String stringPool = null;
    public void put(String s){
        stringPool = s;
    }
    public String get(){
        String ret = stringPool;
        stringPool = null;
        return ret;
    }
}

线程impl类如下:

public class WaitNotifyTest implements Runnable {
    private String threadType;
    public ConsumerProducer cp;
    public static volatile int i = 1;
    public WaitNotifyTest(String threadType, ConsumerProducer cp) {
        this.threadType = threadType;
        this.cp = cp;
    }
    public static void main(String[] args) throws InterruptedException {
        ConsumerProducer cp = new ConsumerProducer();
        WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
        WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);
        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test2);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
    @Override
    public void run() {
        while (true) {
            if (threadType.equalsIgnoreCase("Consumer")) {
                synchronized (cp) {
                    try {
                        if (null != cp.get()) {
                            cp.wait();
                        }
                        consume();
                        System.out.println("notify from Consumer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                synchronized (cp) {
                    try {
                        if (null == cp.get()) {
                            cp.wait();
                        }
                        produce();
                        System.out.println("notify from Producer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (i == 5) {
                break;
            }
            i++;
        }
    }
    public void consume() {
        System.out.println("Putting: Counter" + i);
        cp.put("Counter" + i);
    }
    public void produce() {
        System.out.println("getting: " + cp.get());
    }
}

但当我运行代码时,它面临着某种死锁,并且像一样打印

Putting: Counter3
notify from Consumer

出了严重的问题,但我无法辨认。请帮忙。

消费者在做生产者的工作,生产者在做消费者的工作。交换自己的责任并修改条件等待。请参阅下面的代码。

  1. 消费者会在没有东西的时候等待,他会释放cp的锁。这样生产者就有机会进入同步块
  2. 制片人只有在什么都没有的时候才会制作,否则他会等待。之后,他将释放cp的锁。这样消费者就有机会进入同步块
  3. 消费者是把东西拿走的人
  4. 制片人是把事情摆到桌面上的人
  5. 根据您的评论。您想把Counter从1放到5,所以您应该只在Producer线程中添加i++。如何控制它在两个线程中的增加
  6. 您不会判断是消费者还是生产者从cp对象调用get(),而是将null分配给stringPool。这显然是错误的,会使消费者从公共空间中获得零。我添加了一个新方法clearString(),它只在消费者消费了产品时才将公共空间设置为null。

    public class WaitNotifyTest implements Runnable {
    private String threadType;
    public ConsumerProducer cp;
    public static volatile int i = 0;
    public WaitNotifyTest(String threadType, ConsumerProducer cp) {
        this.threadType = threadType;
        this.cp = cp;
    }
    public static void main(String[] args) throws InterruptedException {
        ConsumerProducer cp = new ConsumerProducer();
        WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
        WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);
        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test2);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
    @Override
    public void run() {
        while (true) {
            if (threadType.equalsIgnoreCase("Consumer")) {
                synchronized (cp) {
                    try {
                        /*
                         * Consumer will wait when there is nothing to get and he will release the lock of cp.
                         * So that producer has change to go into the synchronized block.
                         */
                        if (null == cp.get()) {
                            cp.wait();
                        }
                        consume();
                        System.out.println("notify from Consumer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                synchronized (cp) {
                    try {
                        /*
                         * Producer only produce when there is nothing or he will wait. At the same time, he will release the lock of cp.
                         * So that consumer has chance to go into the synchronized block.
                         */
                        if (null != cp.get()) {
                            cp.wait();
                        }
                        i++;
                        produce();
                        System.out.println("notify from Producer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (i == 5) {
                break;
            }
        }
    }
    public void consume() {
        System.out.println("getting: " + cp.get());
        cp.clearString();
    }
    public void produce() {
        System.out.println("Putting: Counter" + i);
        cp.put("Counter" + i);
    }}
    

另请参阅ConsumerProducer类。

public class ConsumerProducer {
        public String stringPool = null;
        public void put(String s){
            stringPool = s;
        }
        public String get(){
            return stringPool;
        }
        public void clearString(){
            stringPool = null;
        }
}

更新的代码如下:ConsumerProducer.java:
公共类ConsumerProducer{

    public volatile String stringPool = null;
    public void put(String s){
        this.stringPool = s;
    }
    public String get(){
        String ret = this.stringPool;
        //this.stringPool = null;
        return ret;
    }
    //added
    public void clearString(){
        this.stringPool = null;
    }
}

WaitNotifyTest.java公共类WaitNotifyTest实现Runnable{

    private String threadType;
    public ConsumerProducer cp;
    public static volatile int i = 0;
    public WaitNotifyTest(String threadType, ConsumerProducer cp) {
        this.threadType = threadType;
        this.cp = cp;
    }
    public static void main(String[] args) throws InterruptedException {
        ConsumerProducer cp = new ConsumerProducer();
        WaitNotifyTest test1 = new WaitNotifyTest("Consumer", cp);
        WaitNotifyTest test2 = new WaitNotifyTest("Producer", cp);
        Thread t1 = new Thread(test1);
        Thread t2 = new Thread(test2);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
    }
    @Override
    public void run() {
        while (true) {
            if (threadType.equalsIgnoreCase("Consumer")) {
                synchronized (cp) {
                    try {
                        if (null == cp.get()) {
                            cp.wait();
                        }
                        consume();
                        System.out.println("notify from Consumer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } else {
                synchronized (cp) {
                    try {
                        if (null != cp.get()) {
                            cp.wait();
                        }
                        i++;
                        produce();
                        System.out.println("notify from Producer");
                        cp.notify();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (i == 5) {
                break;
            }
        }
    }
    public void produce() {
        System.out.println("Putting: Counter" + i);
        cp.put("Counter" + i);
    }
    public void consume() {
        System.out.println("getting: " + cp.get());
        cp.clearString();
    }
}

最新更新