为什么等待/通知不会发生在这里?

时间:2013-06-02 17:01:57

标签: java multithreading

我正在尝试使用int itemHolder只有一个条目的消费者生产者问题。我不知道为什么消费者线程在放置项目时没有通知生产者线程。预期的行为是消费者线程等待生产者将项目放入itemHolder。 另一方面,当我在外部mutax对象上使用锁定时,它可以很好地工作。

public class ProducerConsumer {

    public static void main(String... args) {
        new ProducerConsumer().execute();
    }

    private volatile int itemHolder = -1; // -1 value represent that ItemHolder is empty

    private void execute() {
        final Thread producer = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i < 5; i++) {
                    synchronized (this){
                        while (itemHolder != -1){ // ItemHolder is full
                            try {
                                this.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        itemHolder = i;
                        notify();
                        System.out.println(String.format("producer: ItemHolder has value, Consumer notified..."));

                    }
                }

            }


        }, "Producer-thread");

        final Thread consumer = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    synchronized (producer){
                        try {
                            while (itemHolder == -1){ // Don't consume if itemHolder don't have a value
                                producer.wait();
                            }
                            System.out.println(String.format("CONSUMER: consuming %s...", itemHolder));
                            itemHolder = -1;    // re-initialize the itemHolder
                            producer.notify();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }
        }, "Consumer-thread");

        consumer.start();
        producer.start();

    }

锁定外部互斥锁  这可以正常工作。

public class ProducerConsumerWithMutex {

    public static void main(String... args) {
        new ProducerConsumerWithMutex().execute();
    }
    private final String mutex = "";
    private volatile int itemHolder = -1;

    private void execute() {
        final Thread producer = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i < 5; i++) {
                    synchronized (mutex){
                        while (itemHolder != -1){ // itemHolder is full
                            try {
                                mutex.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        itemHolder = i;
                        System.out.println(String.format("producer: producing %s...", i));
                        mutex.notify();
                        System.out.println(String.format("producer: Consumer notified, itemHolder has item..."));

                    }
                }

            }


        }, "Producer-thread");

        final Thread consumer = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    synchronized (mutex){
                        try {
                            while (itemHolder == -1){
                                System.out.println("CONSUMER: itemHolder is empty, waiting...");
                                mutex.wait();
                            }
                            System.out.println(String.format("CONSUMER: consuming %s...", itemHolder));
                            itemHolder = -1;
                            mutex.notify();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }
        }, "Consumer-thread");

        consumer.start();
        producer.start();

    }

3 个答案:

答案 0 :(得分:4)

因为在第一个生成器中,您在this上进行同步,这是Runnable,而不是生成器本身。

所以你需要使用synchronized(producer)代替,但它不会编译,因为producer在该行上尚不可用。

或者你可以命名你的Runnable:

Runnable producerRunnable = ...; //synchronized on this

并在您的消费者中:

synchronized(producerRunnable) {...}

但是你使用单独的互斥锁的第二种方法是可取的,除了锁定""是一个非常糟糕的主意,因为这是一个全局常量(空字符串在字符串池中)。你应该更喜欢这样的东西:

private final Object mutex = new Object();

答案 1 :(得分:1)

当两个线程都使用相同的对象/类锁时,等待通知工作。在您的情况下,用于等待/通知的锁是不同的,如下所述:

synchronized(producer) // lock on producer object

synchronized(this) // Runnable object.

答案 2 :(得分:0)

在supportig assylias之后'这里的回答是另一种选择。

private Object lock = new Object();

锁定

synchronized (lock){
      lock.wait();
}

解锁

synchronized (lock){
      lock.notify();
}