Ожидает ли wait () объект ссылки или саму ссылку, если она вызывается по ссылке? - PullRequest
0 голосов
/ 24 мая 2018

В этом случае будет ли поток 1 фактически уведомлен (при ожидании ссылки вместо самого объекта)?

static Object lock=new Object();
//Thread 1:
Object reference=lock;
reference.wait();

//Thread 2:
lock.notify();

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Ожидание ссылки или объекта, на который указывает эта ссылка, - это то же самое, так как для объекта получена блокировка.Независимо от количества ссылок, если они указывают на один и тот же объект в памяти, wait (), notify (), notifyall () будут работать без проблем.Проверьте приведенный ниже код.

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

public class ProducerConsumer {

private Queue<Integer>      queue   = new ArrayBlockingQueue<>(10);
private LinkedList<Integer> list    = new LinkedList<>();
int                         limit   = 10;

public static void main(String[] args) {

    final ProducerConsumer pc = new ProducerConsumer();
    final ProducerConsumer pcRef = pc;

    Thread producer = new Thread(new Runnable() {
        int i = 1;

        @Override
        public void run() {
            while (true) {
                synchronized (pcRef) {
                    while (pc.limit == pc.list.size()) {
                        try {
                            pcRef.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    pc.list.add(i);
                    System.out.println("Producer @work : " + pc.list.size());
                    pcRef.notify();
                }

            }
        }
    });

    Thread consumer = new Thread(new Runnable() {

        @Override
        public void run() {
            while (true) {
                synchronized (pc) {
                    while (0 == pc.list.size()) {
                        try {
                            pc.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    int val = pc.list.removeFirst();
                    System.out.println("Consumer @work : " + pc.list.size() + " : " + val);
                    pc.notify();
                }

            }
        }
    });

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

    try {
        producer.join();
        consumer.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

}

Прокомментируйте приведенную ниже строку, и вы увидите, что поток потребителя ожидает уведомления.

pc.list.add(i);
System.out.println("Producer @work : " + pc.list.size());
//pcRef.notify();
0 голосов
/ 24 мая 2018

Синхронизированный метод оценивает выражение, данное синхронизированному блоку, чтобы выяснить, какую блокировку взять.Затем необходимо вызвать, уведомить и т. Д. Для одного и того же объекта, но использование той же переменной не имеет значения.Код оценивает выражение, чтобы получить объект.

Теперь вопрос о том, ждет ли поток 1, получает ли он уведомление и просыпается, зависит от состояния гонки.Если поток1 входит в метод ожидания до того, как поток2 вызовет уведомление, тогда поток2 будет ждать, а затем проснется, как только поток2 уведомит.Если thread2 вызывает notify до того, как thread1 входит в метод wait, то thread1 ждет вечно.

...