Предотвращение одновременного доступа к методу в сервлете - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть метод в сервлете, который вставляет заказы на обучение в базу данных.У этого метода есть бизнес-правило, которое проверяет, занят ли репетитор этого сеанса в эту дату и час.Код выглядит примерно так:

class BookingService {
    public void insert(Booking t) {
        if(available(t.getTutor(), t.getDate(), t.getTime())) {
            bookingDao.insert(t);
        } else {
            // reject
        }
    }
}

Проблема в том, что несколько пользователей могут одновременно пытаться забронировать одного и того же репетитора в одну и ту же дату и время, и ничто не мешает им и пройти тест, ивставить свои заказы.Я пытался синхронизировать insert() и использовать блокировки, но это не работает.Как я могу предотвратить одновременный доступ к этому методу?

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

Использование синхронизированного является неадекватным способом решения этой проблемы:

Во-первых, вы закодируете свое приложение, чтобы одновременно можно было развернуть только один экземпляр.Это не только масштабирование в облаке.Для ИТ-отдела является нормальным хотеть поднять более одного экземпляра приложения, чтобы это не было единственной точкой отказа (так что в случае, если ящик, на котором размещен один экземпляр, выходит из строя, приложение все еще доступно).Использование статической синхронизации означает, что блокировка не выходит за пределы одного загрузчика классов приложения, поэтому несколько экземпляров могут чередовать свою работу, подверженную ошибкам.

Если вы в какой-то момент должны покинуть проект, последующие сопровождающие могут не знать об этой проблеме и могут попытаться развернуть приложение так, как вы этого не планировали.Используя синхронизированные средства, вы оставите наземную мину, чтобы они могли наткнуться на нее.

Во-вторых, использование синхронизированного блока препятствует параллелизму вашего приложения, поскольку за один раз может выполняться только один поток.

Итак, вы ввели узкое место и в то же время отменили способность операций обходить узкое место путем развертывания второго экземпляра.Не очень хорошее решение

Поскольку в опубликованном коде нет признаков того, где находятся транзакции, я предполагаю, что либо каждый DAO создает свою собственную транзакцию, либо вы подключаетесь в режиме автоматической фиксации.Базы данных предоставляют транзакции для решения этой проблемы, и, поскольку эта функция реализована в базе данных, она будет работать независимо от того, сколько экземпляров приложения запущено.

Простым способом решения проблемы, которая позволила бы избежать вышеуказанных недостатков, было бы поместить транзакцию на уровень обслуживания, чтобы все вызовы DAO выполнялись в одной транзакции.Служебный уровень может получить соединение с базой данных из пула, запустить транзакцию, передать соединение каждому вызову метода DAO, зафиксировать транзакцию и затем вернуть соединение в пул.

0 голосов
/ 28 декабря 2018

Одним из способов решения проблемы является использование блока synchronized.Есть много вещей, которые вы можете выбрать в качестве объекта блокировки - на данный момент this должно быть в порядке:

class BookingService {
    public void insert(Booking t) {
        synchronized(this) {
            if(available(t.getTutor(), t.getDate(), t.getTime())) {
                bookingDao.insert(t);
            } else {
                // reject
            }
        }
    }
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...