#java #многопоточность #синхронизация
В интернете нашел пример использования wait и notify: public class ThreadsApp { public static void main(String[] args) { Store store = new Store(); Producer producer = new Producer(store); Consumer consumer = new Consumer(store); new Thread(producer).start(); new Thread(consumer).start(); } } // Класс Магазин, хранящий произведенные товары class Store { private int product = 0; private boolean available = false; public synchronized void get() { while (product < 1) { try { wait(); } catch (InterruptedException e) { } } product--; System.out.println("Покупатель купил 1 товар"); System.out.println("Товаров на складе: " + product); notify(); } public synchronized void put() { while (product >= 3) { try { wait(); } catch (InterruptedException e) { } } product++; System.out.println("Производитель добавил 1 товар"); System.out.println("Товаров на складе: " + product); notify(); } } // класс Производитель class Producer implements Runnable { Store store; Producer(Store store) { this.store = store; } public void run() { for (int i = 1; i < 6; i++) { store.put(); } } } // Класс Потребитель class Consumer implements Runnable { Store store; Consumer(Store store) { this.store = store; } public void run() { for (int i = 1; i < 6; i++) { store.get(); } } } Вопрос: В реализации методов get и put есть метод notify, который будит потоки, спящие на мониторе store, и это происходит каждый раз при их вызове, т.е. когда поток покупатель купил товар и вызвал notify в методе get, поток производитель на этом же мониторе УЖЕ ПРОСНУЛСЯ И ЖДЕТ ОСВОБОЖДЕНИЯ МОНИТОРА? Так как вызывается несколько раз notify, потому что вызывается несколько раз get и put, столько же раз происходит пробуждение потоков на мониторе, получается поток уже проснулся, и его еще 2 раза будят - как это с точки зрения правильности?
Ответы
Ответ 1
notify - будит только 1 поток и не известно какой именно. Если никто не ждет, то notify ничего не делает. Попробую пояснить подробно. Поток А захватывает lock и входит в синхронизированный код. Поток А вызывает wait, засыпает и освобождает lock. Поток Б захватывает lock и входит в синхронизированный код. Поток Б вызывает notify. Возможно (так как не известно какой поток будет разбужен) поток А просыпается становится в очередь на захват lock. Поток Б освобождает lock и выходит из синхронизированного кода. Поток А захватывает lock и продолжает со следующего после wait выражения.
Комментариев нет:
Отправить комментарий