Как правильно использовать Java-уведомления в реализации блокировки очереди - PullRequest
1 голос
/ 27 июня 2011

Я пытаюсь понять многопоточные конструкции Java и пытаюсь написать простую реализацию очереди блокировки.Вот код, который я написал:

  class BlockingBoundedQueue<E>
    {
        @SuppressWarnings("unchecked")
        BlockingBoundedQueue(int size)
        {
            fSize = size;
            fArray = (E[]) new Object[size];
//            fBlockingQueue = new ArrayBlockingQueue<E>(size);
        }

        BlockingQueue<E> fBlockingQueue;

        public synchronized void put(E elem)
        {
            if(fCnt==fSize-1)
            {
                try
                {
                    // Should I be waiting/locking on the shared array instead ? how ?
                    wait();
                }
                catch (InterruptedException e)
                {
                    throw new RuntimeException("Waiting thread was interrupted during put with msg:",e);
                }
            }
            else
            {
                fArray[fCnt++]=elem;
                //How to notify threads waiting during take()
            }
        }


        public synchronized E take()
        {
            if(fCnt==0)
            {
                try
                {
                    // Should I be waiting/locking on the shared array instead ? how ?
                    wait();
                }
                catch (InterruptedException e)
                {
                    throw new RuntimeException("Waiting thread was interrupted during take with msg:",e);
                }
            }

            return fArray[fCnt--];
            //How to notify threads waiting during put()
        }
        private int fCnt;
        private int fSize;
        private E[] fArray; 

    }

Я хочу уведомить потоки, ожидающие в Take () от put () и наоборот.Может кто-нибудь, пожалуйста, помогите мне с правильным способом сделать это.

Я проверил реализацию java.utils, и она использует Condition и ReentrantLocks, которые на данном этапе немного сложны для меня.Я в порядке, пока я не полностью устойчив (но исправлен) ради простоты.

Спасибо!

1 Ответ

2 голосов
/ 27 июня 2011

Короткий ответ: позвоните notifyAll(), где у вас есть комментарии //How to notify threads waiting during take()

Теперь для более полного ответа ...

Ссылка для чтения: Параллелизм Java на практике . Ответ на ваш вопрос там.

Однако, чтобы кратко ответить на ваш вопрос: в Java потоки синхронизируются путем блокировки одного и того же объекта и использования wait() и notify() для безопасного изменения состояния. Типичный упрощенный поток:

  1. Поток A получает блокировку, вводя блок synchronized на объекте блокировки
  2. Поток A проверяет некоторые условия в цикле, если не вызов «OK to go» thread.wait(), который является блокирующим вызовом, который «снимает» блокировку, поэтому другой код, синхронизированный с тем же объектом блокировки, может продолжаться
  3. Поток B получает такую ​​же блокировку и может делать что-то, что изменяет условие, которое ожидает поток A. Когда он вызывает notifyAll(), поток A проснется и перепроверит условие и (может) продолжить

Некоторые вещи, которые нужно помнить о синхронизации:

  • Речь идет о поддержании согласованного состояния объектов путем внесения изменений в состояние atomic . «Атомная» означает, что все изменение (например, для нескольких полей) гарантированно завершено (без частичных и, следовательно, несогласованных изменений)
  • это кооперативно - код, синхронизируемый с данным объектом блокировки, имеет общее состояние, которое изменяется, и условия, которые позволяют этому состоянию меняться - вы wait и notify об одном и том же «субъекте». Каждая часть состояния должна быть защищена своим собственным объектом блокировки - обычно частным полем, например, private Object lock = new Object(); было бы хорошо
  • Методы, которые синхронизируются, используют this в качестве объекта блокировки - это легко, но потенциально дорого, потому что вы блокируете для каждого вызова вместо того, когда вам нужно
  • статические методы, которые синхронизируются, используют объект Class в качестве объекта блокировки
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...