Будет ли использование ограниченного буфера (производителя / потребителя) избежать боли при использовании методов синхронизации / взаимоблокировок? - PullRequest
0 голосов
/ 19 октября 2011

Я пишу простой банковский симулятор, в котором пользователи будут входить из разных мест одновременно, используя сокеты. На сервере Банка я сохраняю ограниченный буфер для хранения каждого входящего запроса, например: перевод средств, получение остатка на счете и т. Д., И на стороне сервера выполняется фоновый поток (Buffer Reader) для извлечения каждого запроса из этой очереди запросов (предположим, что он работает как планировщик потоков в ОС), в основе FCFS.

Я сделал методы put () и get () буфера для условной синхронизации.

например:

// put method
while(total_buffer_size == current_total_requests) {

 System.out.println("Buffer is full");
 wait();

}

Итак, мой вопрос: мы должны синхронизировать методы , такие как get-balance или Transfer-Fund, чтобы избежать повреждения данных? Я считаю, что в этом нет необходимости, поскольку Buffer Reader выполняет каждый запрос один за другим и соответствующие действия. Избегал ли я каких-либо тупиковых ситуаций благодаря этому? Как вы думаете? Спасибо

РЕДАКТИРОВАТЬ2:

public synchronized boolean put(Messenger msg, Thread t, Socket s) throws InterruptedException {
        while(total_buffer_size  == current_total_requests) {

            System.out.println("Buffer is full");
            wait();

        }
        current_total_requests++;

        requests[cur_req_in] = new Request(msg, s); // insert into Queue

        cur_req_in = (cur_req_in + 1) % total_buffer_size ;

        notifyAll();

        return true;
    }

    // take each incoming message in queue. FIFO rule followed
    public synchronized Request get() throws InterruptedException {

            while(current_total_requests==0) wait();
            Request out = requests[cur_req_out];
            requests[cur_req_out] = null;

            cur_req_out = (cur_req_out + 1) % total_buffer_size ;
            current_total_requests--;
            notifyAll(); //wake all waiting threads to continue put()
            return out;

    }

1 Ответ

1 голос
/ 19 октября 2011

Если есть только один потребитель (то есть один поток, который потребляет запросы из «буфера»), то вам не нужно использовать синхронизацию для методов, относящихся к банковскому счету. Однако я не верю, что ваша текущая реализация «ограниченного буфера» является действительной. Чтобы быть более конкретным:

while(total_buffer_size == current_total_requests) {

 System.out.println("Buffer is full");
 wait();

}

Нет абсолютно никакой гарантии, сколько потоков пройдёт цикл while, произведите переключение контекста непосредственно перед увеличением current_total_requests и поставьте в очередь больше запросов, чем допустимый размер буфера. Если ваш метод put не будет синхронизирован, этот подход будет крайне ненадежным и подверженным условиям гонки.

Если вы хотите ограниченный буфер, просто используйте один из уже существующих «ограниченных буферов» Java или, более конкретно: BlockingQueue . Блоки BlockingQueue на put(...):

Вставляет указанный элемент в эту очередь, ожидая, если необходимо, чтобы освободилось место.

Также блокируется на take(), если в очереди нет данных. Я не знаю, можете ли вы использовать один из элементов в библиотеке параллелизма, но если вы не можете, то вам нужно исправить свой BoundedBuffer.

...